Merge commit 'cb4c5e0f0d28bcd66b313d1c38ef82abbbddcf4d' into HEAD
diff --git a/v4/froyo/android/support/v4/content/ContextCompatFroyo.java b/v4/froyo/android/support/v4/content/ContextCompatFroyo.java
new file mode 100644
index 0000000..1fc2f8d
--- /dev/null
+++ b/v4/froyo/android/support/v4/content/ContextCompatFroyo.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2013 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.support.v4.content;
+
+import android.content.Context;
+
+import java.io.File;
+
+class ContextCompatFroyo {
+    public static File getExternalCacheDir(Context context) {
+        return context.getExternalCacheDir();
+    }
+
+    public static File getExternalFilesDir(Context context, String type) {
+        return context.getExternalFilesDir(type);
+    }
+}
diff --git a/v4/honeycomb/android/support/v4/content/ContextCompatHoneycomb.java b/v4/honeycomb/android/support/v4/content/ContextCompatHoneycomb.java
index 736e6f2..9abc97d 100644
--- a/v4/honeycomb/android/support/v4/content/ContextCompatHoneycomb.java
+++ b/v4/honeycomb/android/support/v4/content/ContextCompatHoneycomb.java
@@ -19,6 +19,8 @@
 import android.content.Context;
 import android.content.Intent;
 
+import java.io.File;
+
 /**
  * Implementation of context compatibility that can call Honeycomb APIs.
  */
@@ -27,4 +29,8 @@
     static void startActivities(Context context, Intent[] intents) {
         context.startActivities(intents);
     }
+
+    public static File getObbDir(Context context) {
+        return context.getObbDir();
+    }
 }
diff --git a/v4/java/android/support/v4/app/ActionBarDrawerToggle.java b/v4/java/android/support/v4/app/ActionBarDrawerToggle.java
index 1fc08d8..5c7e733 100644
--- a/v4/java/android/support/v4/app/ActionBarDrawerToggle.java
+++ b/v4/java/android/support/v4/app/ActionBarDrawerToggle.java
@@ -22,9 +22,8 @@
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LevelListDrawable;
+import android.graphics.drawable.InsetDrawable;
 import android.os.Build;
-import android.support.v4.graphics.drawable.DrawableCompat;
 import android.support.v4.view.GravityCompat;
 import android.support.v4.view.ViewCompat;
 import android.support.v4.widget.DrawerLayout;
@@ -138,11 +137,34 @@
         }
     }
 
+    private static class ActionBarDrawerToggleImplJellybeanMR2
+            implements ActionBarDrawerToggleImpl {
+        @Override
+        public Drawable getThemeUpIndicator(Activity activity) {
+            return ActionBarDrawerToggleJellybeanMR2.getThemeUpIndicator(activity);
+        }
+
+        @Override
+        public Object setActionBarUpIndicator(Object info, Activity activity,
+                Drawable themeImage, int contentDescRes) {
+            return ActionBarDrawerToggleJellybeanMR2.setActionBarUpIndicator(info, activity,
+                    themeImage, contentDescRes);
+        }
+
+        @Override
+        public Object setActionBarDescription(Object info, Activity activity, int contentDescRes) {
+            return ActionBarDrawerToggleJellybeanMR2.setActionBarDescription(info, activity,
+                    contentDescRes);
+        }
+    }
+
     private static final ActionBarDrawerToggleImpl IMPL;
 
     static {
         final int version = Build.VERSION.SDK_INT;
-        if (version >= 11) {
+        if (version >= 18) {
+            IMPL = new ActionBarDrawerToggleImplJellybeanMR2();
+        } else if (version >= 11) {
             IMPL = new ActionBarDrawerToggleImplHC();
         } else {
             IMPL = new ActionBarDrawerToggleImplBase();
@@ -382,7 +404,7 @@
                 .setActionBarDescription(mSetIndicatorInfo, mActivity, contentDescRes);
     }
 
-    private class SlideDrawable extends LevelListDrawable implements Drawable.Callback {
+    private class SlideDrawable extends InsetDrawable implements Drawable.Callback {
         private final boolean mHasMirroring = Build.VERSION.SDK_INT > 18;
         private final Rect mTmpRect = new Rect();
 
@@ -390,13 +412,7 @@
         private float mOffset;
 
         private SlideDrawable(Drawable wrapped) {
-            super();
-
-            if (DrawableCompat.isAutoMirrored(wrapped)) {
-                DrawableCompat.setAutoMirrored(this, true);
-            }
-
-            addLevel(0, 0, wrapped);
+            super(wrapped, 0);
         }
 
         /**
diff --git a/v4/java/android/support/v4/content/ContextCompat.java b/v4/java/android/support/v4/content/ContextCompat.java
index 6acf97e..8fbf4bb 100644
--- a/v4/java/android/support/v4/content/ContextCompat.java
+++ b/v4/java/android/support/v4/content/ContextCompat.java
@@ -16,11 +16,15 @@
 
 package android.support.v4.content;
 
-import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Environment;
+import android.os.StatFs;
+import android.support.v4.os.EnvironmentCompat;
+
+import java.io.File;
 
 /**
  * Helper for accessing features in {@link android.content.Context}
@@ -28,6 +32,12 @@
  */
 public class ContextCompat {
 
+    private static final String DIR_ANDROID = "Android";
+    private static final String DIR_DATA = "data";
+    private static final String DIR_OBB = "obb";
+    private static final String DIR_FILES = "files";
+    private static final String DIR_CACHE = "cache";
+
     /**
      * Start a set of activities as a synthesized task stack, if able.
      *
@@ -96,4 +106,195 @@
         }
         return false;
     }
+
+    /**
+     * Returns absolute paths to application-specific directories on all
+     * external storage devices where the application's OBB files (if there are
+     * any) can be found. Note if the application does not have any OBB files,
+     * these directories may not exist.
+     * <p>
+     * This is like {@link Context#getFilesDir()} in that these files will be
+     * deleted when the application is uninstalled, however there are some
+     * important differences:
+     * <ul>
+     * <li>External files are not always available: they will disappear if the
+     * user mounts the external storage on a computer or removes it.
+     * <li>There is no security enforced with these files.
+     * </ul>
+     * <p>
+     * External storage devices returned here are considered a permanent part of
+     * the device, including both emulated external storage and physical media
+     * slots, such as SD cards in a battery compartment. The returned paths do
+     * not include transient devices, such as USB flash drives.
+     * <p>
+     * An application may store data on any or all of the returned devices. For
+     * example, an app may choose to store large files on the device with the
+     * most available space, as measured by {@link StatFs}.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
+     * are required to write to the returned paths; they're always accessible to
+     * the calling app. Before then,
+     * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to
+     * write. Write access outside of these paths on secondary external storage
+     * devices is not available. To request external storage access in a
+     * backwards compatible way, consider using {@code android:maxSdkVersion}
+     * like this:
+     *
+     * <pre class="prettyprint">&lt;uses-permission
+     *     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
+     *     android:maxSdkVersion="18" /&gt;</pre>
+     * <p>
+     * The first path returned is the same as {@link Context#getObbDir()}.
+     * Returned paths may be {@code null} if a storage device is unavailable.
+     *
+     * @see Context#getObbDir()
+     * @see EnvironmentCompat#getStorageState(File)
+     */
+    public static File[] getObbDirs(Context context) {
+        final int version = Build.VERSION.SDK_INT;
+        if (version >= 19) {
+            return ContextCompatKitKat.getObbDirs(context);
+        } else {
+            final File single;
+            if (version >= 11) {
+                single = ContextCompatHoneycomb.getObbDir(context);
+            } else {
+                single = buildPath(Environment.getExternalStorageDirectory(), DIR_ANDROID, DIR_OBB,
+                        context.getPackageName());
+            }
+            return new File[] { single };
+        }
+    }
+
+    /**
+     * Returns absolute paths to application-specific directories on all
+     * external storage devices where the application can place persistent files
+     * it owns. These files are internal to the application, and not typically
+     * visible to the user as media.
+     * <p>
+     * This is like {@link Context#getFilesDir()} in that these files will be
+     * deleted when the application is uninstalled, however there are some
+     * important differences:
+     * <ul>
+     * <li>External files are not always available: they will disappear if the
+     * user mounts the external storage on a computer or removes it.
+     * <li>There is no security enforced with these files.
+     * </ul>
+     * <p>
+     * External storage devices returned here are considered a permanent part of
+     * the device, including both emulated external storage and physical media
+     * slots, such as SD cards in a battery compartment. The returned paths do
+     * not include transient devices, such as USB flash drives.
+     * <p>
+     * An application may store data on any or all of the returned devices. For
+     * example, an app may choose to store large files on the device with the
+     * most available space, as measured by {@link StatFs}.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
+     * are required to write to the returned paths; they're always accessible to
+     * the calling app. Before then,
+     * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to
+     * write. Write access outside of these paths on secondary external storage
+     * devices is not available. To request external storage access in a
+     * backwards compatible way, consider using {@code android:maxSdkVersion}
+     * like this:
+     *
+     * <pre class="prettyprint">&lt;uses-permission
+     *     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
+     *     android:maxSdkVersion="18" /&gt;</pre>
+     * <p>
+     * The first path returned is the same as
+     * {@link Context#getExternalFilesDir(String)}. Returned paths may be
+     * {@code null} if a storage device is unavailable.
+     *
+     * @see Context#getExternalFilesDir(String)
+     * @see EnvironmentCompat#getStorageState(File)
+     */
+    public static File[] getExternalFilesDirs(Context context, String type) {
+        final int version = Build.VERSION.SDK_INT;
+        if (version >= 19) {
+            return ContextCompatKitKat.getExternalFilesDirs(context, type);
+        } else {
+            final File single;
+            if (version >= 8) {
+                single = ContextCompatFroyo.getExternalFilesDir(context, type);
+            } else {
+                single = buildPath(Environment.getExternalStorageDirectory(), DIR_ANDROID, DIR_DATA,
+                        context.getPackageName(), DIR_FILES, type);
+            }
+            return new File[] { single };
+        }
+    }
+
+    /**
+     * Returns absolute paths to application-specific directories on all
+     * external storage devices where the application can place cache files it
+     * owns. These files are internal to the application, and not typically
+     * visible to the user as media.
+     * <p>
+     * This is like {@link Context#getCacheDir()} in that these files will be
+     * deleted when the application is uninstalled, however there are some
+     * important differences:
+     * <ul>
+     * <li>External files are not always available: they will disappear if the
+     * user mounts the external storage on a computer or removes it.
+     * <li>There is no security enforced with these files.
+     * </ul>
+     * <p>
+     * External storage devices returned here are considered a permanent part of
+     * the device, including both emulated external storage and physical media
+     * slots, such as SD cards in a battery compartment. The returned paths do
+     * not include transient devices, such as USB flash drives.
+     * <p>
+     * An application may store data on any or all of the returned devices. For
+     * example, an app may choose to store large files on the device with the
+     * most available space, as measured by {@link StatFs}.
+     * <p>
+     * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
+     * are required to write to the returned paths; they're always accessible to
+     * the calling app. Before then,
+     * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} is required to
+     * write. Write access outside of these paths on secondary external storage
+     * devices is not available. To request external storage access in a
+     * backwards compatible way, consider using {@code android:maxSdkVersion}
+     * like this:
+     *
+     * <pre class="prettyprint">&lt;uses-permission
+     *     android:name="android.permission.WRITE_EXTERNAL_STORAGE"
+     *     android:maxSdkVersion="18" /&gt;</pre>
+     * <p>
+     * The first path returned is the same as
+     * {@link Context#getExternalCacheDir()}. Returned paths may be {@code null}
+     * if a storage device is unavailable.
+     *
+     * @see Context#getExternalCacheDir()
+     * @see EnvironmentCompat#getStorageState(File)
+     */
+    public static File[] getExternalCacheDirs(Context context) {
+        final int version = Build.VERSION.SDK_INT;
+        if (version >= 19) {
+            return ContextCompatKitKat.getExternalCacheDirs(context);
+        } else {
+            final File single;
+            if (version >= 8) {
+                single = ContextCompatFroyo.getExternalCacheDir(context);
+            } else {
+                single = buildPath(Environment.getExternalStorageDirectory(), DIR_ANDROID, DIR_DATA,
+                        context.getPackageName(), DIR_CACHE);
+            }
+            return new File[] { single };
+        }
+    }
+
+    private static File buildPath(File base, String... segments) {
+        File cur = base;
+        for (String segment : segments) {
+            if (cur == null) {
+                cur = new File(segment);
+            } else if (segment != null) {
+                cur = new File(cur, segment);
+            }
+        }
+        return cur;
+    }
 }
diff --git a/v4/java/android/support/v4/os/EnvironmentCompat.java b/v4/java/android/support/v4/os/EnvironmentCompat.java
new file mode 100644
index 0000000..66a2a8e
--- /dev/null
+++ b/v4/java/android/support/v4/os/EnvironmentCompat.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.support.v4.os;
+
+import android.os.Build;
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Helper for accessing features in {@link Environment} introduced after API
+ * level 4 in a backwards compatible fashion.
+ */
+public class EnvironmentCompat {
+    private static final String TAG = "EnvironmentCompat";
+
+    /**
+     * Unknown storage state, such as when a path isn't backed by known storage
+     * media.
+     *
+     * @see #getStorageState(File)
+     */
+    public static final String MEDIA_UNKNOWN = "unknown";
+
+    /**
+     * Returns the current state of the storage device that provides the given
+     * path.
+     *
+     * @return one of {@link #MEDIA_UNKNOWN}, {@link Environment#MEDIA_REMOVED},
+     *         {@link Environment#MEDIA_UNMOUNTED},
+     *         {@link Environment#MEDIA_CHECKING},
+     *         {@link Environment#MEDIA_NOFS},
+     *         {@link Environment#MEDIA_MOUNTED},
+     *         {@link Environment#MEDIA_MOUNTED_READ_ONLY},
+     *         {@link Environment#MEDIA_SHARED},
+     *         {@link Environment#MEDIA_BAD_REMOVAL}, or
+     *         {@link Environment#MEDIA_UNMOUNTABLE}.
+     */
+    public static String getStorageState(File path) {
+        final int version = Build.VERSION.SDK_INT;
+        if (version >= 19) {
+            return EnvironmentCompatKitKat.getStorageState(path);
+        }
+
+        try {
+            final String canonicalPath = path.getCanonicalPath();
+            final String canonicalExternal = Environment.getExternalStorageDirectory()
+                    .getCanonicalPath();
+
+            if (canonicalPath.startsWith(canonicalExternal)) {
+                return Environment.getExternalStorageState();
+            }
+        } catch (IOException e) {
+            Log.w(TAG, "Failed to resolve canonical path: " + e);
+        }
+
+        return MEDIA_UNKNOWN;
+    }
+}
diff --git a/v4/java/android/support/v4/print/PrintHelper.java b/v4/java/android/support/v4/print/PrintHelper.java
index 0d3c5ba..5e3ef3c 100644
--- a/v4/java/android/support/v4/print/PrintHelper.java
+++ b/v4/java/android/support/v4/print/PrintHelper.java
@@ -47,6 +47,16 @@
      */
     public static final int COLOR_MODE_COLOR = 2;
 
+    /**
+     * Print the image in landscape orientation (default).
+     */
+    public static final int ORIENTATION_LANDSCAPE = 1;
+
+    /**
+     * Print the image in  portrait orientation.
+     */
+    public static final int ORIENTATION_PORTRAIT = 2;
+
     PrintHelperVersionImpl mImpl;
 
     /**
@@ -75,6 +85,10 @@
 
         public int getColorMode();
 
+        public void setOrientation(int orientation);
+
+        public int getOrientation();
+
         public void printBitmap(String jobName, Bitmap bitmap);
 
         public void printBitmap(String jobName, Uri imageFile)
@@ -87,7 +101,7 @@
     private static final class PrintHelperStubImpl implements PrintHelperVersionImpl {
         int mScaleMode = SCALE_MODE_FILL;
         int mColorMode = COLOR_MODE_COLOR;
-
+        int mOrientation = ORIENTATION_LANDSCAPE;
         @Override
         public void setScaleMode(int scaleMode) {
             mScaleMode = scaleMode;
@@ -104,6 +118,12 @@
         }
 
         @Override
+        public void setOrientation(int orientation) { mOrientation = orientation; }
+
+        @Override
+        public int getOrientation() { return mOrientation; }
+
+        @Override
         public int getScaleMode() {
             return mScaleMode;
         }
@@ -121,40 +141,50 @@
      * Implementation used on KitKat (and above)
      */
     private static final class PrintHelperKitkatImpl implements PrintHelperVersionImpl {
-        private final PrintHelperKitkat printHelper;
+        private final PrintHelperKitkat mPrintHelper;
 
         PrintHelperKitkatImpl(Context context) {
-            printHelper = new PrintHelperKitkat(context);
+            mPrintHelper = new PrintHelperKitkat(context);
         }
 
         @Override
         public void setScaleMode(int scaleMode) {
-            printHelper.setScaleMode(scaleMode);
+            mPrintHelper.setScaleMode(scaleMode);
         }
 
         @Override
         public int getScaleMode() {
-            return printHelper.getScaleMode();
+            return mPrintHelper.getScaleMode();
         }
 
         @Override
         public void setColorMode(int colorMode) {
-            printHelper.setColorMode(colorMode);
+            mPrintHelper.setColorMode(colorMode);
         }
 
         @Override
         public int getColorMode() {
-            return printHelper.getColorMode();
+            return mPrintHelper.getColorMode();
+        }
+
+        @Override
+        public void setOrientation(int orientation) {
+            mPrintHelper.setOrientation(orientation);
+        }
+
+        @Override
+        public int getOrientation() {
+            return mPrintHelper.getOrientation();
         }
 
         @Override
         public void printBitmap(String jobName, Bitmap bitmap) {
-            printHelper.printBitmap(jobName, bitmap);
+            mPrintHelper.printBitmap(jobName, bitmap);
         }
 
         @Override
         public void printBitmap(String jobName, Uri imageFile) throws FileNotFoundException {
-            printHelper.printBitmap(jobName, imageFile);
+            mPrintHelper.printBitmap(jobName, imageFile);
         }
     }
 
@@ -218,6 +248,27 @@
     }
 
     /**
+     * Sets whether the image will be printed in landscape {@link #ORIENTATION_LANDSCAPE} (default)
+     * or portrait {@link #ORIENTATION_PORTRAIT}.
+     *
+     * @param orientation The page orientation which is one of
+     *                    {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT}.
+     */
+    public void setOrientation(int orientation) {
+        mImpl.setOrientation(orientation);
+    }
+
+    /**
+     * Gets whether the image will be printed in landscape or portrait.
+     *
+     * @return The page orientation which is one of
+     * {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT}.
+     */
+    public int getOrientation() {
+        return mImpl.getOrientation();
+    }
+
+    /**
      * Prints a bitmap.
      *
      * @param jobName The print job name.
diff --git a/v4/java/android/support/v4/util/MapCollections.java b/v4/java/android/support/v4/util/MapCollections.java
index 051e3b6..5ef5410 100644
--- a/v4/java/android/support/v4/util/MapCollections.java
+++ b/v4/java/android/support/v4/util/MapCollections.java
@@ -95,10 +95,10 @@
             if (!mEntryValid) {
                 throw new IllegalStateException();
             }
+            colRemoveAt(mIndex);
             mIndex--;
             mEnd--;
             mEntryValid = false;
-            colRemoveAt(mIndex);
         }
 
         @Override
diff --git a/v4/java/android/support/v4/widget/DrawerLayout.java b/v4/java/android/support/v4/widget/DrawerLayout.java
index deddb0b..bc7321f 100644
--- a/v4/java/android/support/v4/widget/DrawerLayout.java
+++ b/v4/java/android/support/v4/widget/DrawerLayout.java
@@ -1541,11 +1541,38 @@
 
             superNode.recycle();
 
-            final int childCount = getChildCount();
+            addChildrenForAccessibility(info, (ViewGroup) host);
+        }
+
+        private void addChildrenForAccessibility(AccessibilityNodeInfoCompat info, ViewGroup v) {
+            final int childCount = v.getChildCount();
             for (int i = 0; i < childCount; i++) {
-                final View child = getChildAt(i);
-                if (!filter(child)) {
-                    info.addChild(child);
+                final View child = v.getChildAt(i);
+                if (filter(child)) {
+                    continue;
+                }
+
+                // Adding children that are marked as not important for
+                // accessibility will break the hierarchy, so we need to check
+                // that value and re-parent views if necessary.
+                final int importance = ViewCompat.getImportantForAccessibility(child);
+                switch (importance) {
+                    case ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS:
+                        // Always skip NO_HIDE views and their descendants.
+                        break;
+                    case ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO:
+                        // Re-parent children of NO view groups, skip NO views.
+                        if (child instanceof ViewGroup) {
+                            addChildrenForAccessibility(info, (ViewGroup) child);
+                        }
+                        break;
+                    case ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO:
+                        // Force AUTO views to YES and add them.
+                        ViewCompat.setImportantForAccessibility(
+                                child, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES);
+                    case ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES:
+                        info.addChild(child);
+                        break;
                 }
             }
         }
diff --git a/v4/java/android/support/v4/widget/SlidingPaneLayout.java b/v4/java/android/support/v4/widget/SlidingPaneLayout.java
index 6fc61c4..1c23994 100644
--- a/v4/java/android/support/v4/widget/SlidingPaneLayout.java
+++ b/v4/java/android/support/v4/widget/SlidingPaneLayout.java
@@ -674,7 +674,9 @@
                 mSlideRange = range;
                 lp.dimWhenOffset = xStart + lp.leftMargin + range + childWidth / 2 >
                         width - paddingRight;
-                xStart += (int) (range * mSlideOffset) + lp.leftMargin;
+                final int pos = (int) (range * mSlideOffset);
+                xStart += pos + lp.leftMargin;
+                mSlideOffset = (float) pos / mSlideRange;
             } else if (mCanSlide && mParallaxBy != 0) {
                 offset = (int) ((1 - mSlideOffset) * mParallaxBy);
                 xStart = nextXStart;
@@ -911,6 +913,12 @@
     }
 
     private void onPanelDragged(int newLeft) {
+        if (mSlideableView == null) {
+            // This can happen if we're aborting motion during layout because everything now fits.
+            mSlideOffset = 0;
+            return;
+        }
+
         final LayoutParams lp = (LayoutParams) mSlideableView.getLayoutParams();
         final int leftBound = getPaddingLeft() + lp.leftMargin;
 
diff --git a/v4/jellybean-mr2/android/support/v4/app/ActionBarDrawerToggleJellybeanMR2.java b/v4/jellybean-mr2/android/support/v4/app/ActionBarDrawerToggleJellybeanMR2.java
new file mode 100644
index 0000000..47e8ed9
--- /dev/null
+++ b/v4/jellybean-mr2/android/support/v4/app/ActionBarDrawerToggleJellybeanMR2.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2013 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.support.v4.app;
+
+import android.R;
+import android.app.ActionBar;
+import android.app.Activity;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.Log;
+
+class ActionBarDrawerToggleJellybeanMR2 {
+    private static final String TAG = "ActionBarDrawerToggleImplJellybeanMR2";
+
+    private static final int[] THEME_ATTRS = new int[] {
+            R.attr.homeAsUpIndicator
+    };
+
+    public static Object setActionBarUpIndicator(Object info, Activity activity,
+            Drawable drawable, int contentDescRes) {
+        final ActionBar actionBar = activity.getActionBar();
+        actionBar.setHomeAsUpIndicator(drawable);
+        actionBar.setHomeActionContentDescription(contentDescRes);
+        return info;
+    }
+
+    public static Object setActionBarDescription(Object info, Activity activity,
+            int contentDescRes) {
+        final ActionBar actionBar = activity.getActionBar();
+        actionBar.setHomeActionContentDescription(contentDescRes);
+        return info;
+    }
+
+    public static Drawable getThemeUpIndicator(Activity activity) {
+        final TypedArray a = activity.obtainStyledAttributes(THEME_ATTRS);
+        final Drawable result = a.getDrawable(0);
+        a.recycle();
+        return result;
+    }
+}
diff --git a/v4/kitkat/android/support/v4/content/ContextCompatKitKat.java b/v4/kitkat/android/support/v4/content/ContextCompatKitKat.java
new file mode 100644
index 0000000..6b58827
--- /dev/null
+++ b/v4/kitkat/android/support/v4/content/ContextCompatKitKat.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 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.support.v4.content;
+
+import android.content.Context;
+
+import java.io.File;
+
+class ContextCompatKitKat {
+    public static File[] getExternalCacheDirs(Context context) {
+        return context.getExternalCacheDirs();
+    }
+
+    public static File[] getExternalFilesDirs(Context context, String type) {
+        return context.getExternalFilesDirs(type);
+    }
+
+    public static File[] getObbDirs(Context context) {
+        return context.getObbDirs();
+    }
+}
diff --git a/v4/kitkat/android/support/v4/os/EnvironmentCompatKitKat.java b/v4/kitkat/android/support/v4/os/EnvironmentCompatKitKat.java
new file mode 100644
index 0000000..9a803db
--- /dev/null
+++ b/v4/kitkat/android/support/v4/os/EnvironmentCompatKitKat.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 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.support.v4.os;
+
+import android.os.Environment;
+
+import java.io.File;
+
+class EnvironmentCompatKitKat {
+    public static String getStorageState(File path) {
+        return Environment.getStorageState(path);
+    }
+}
diff --git a/v4/kitkat/android/support/v4/print/PrintHelperKitkat.java b/v4/kitkat/android/support/v4/print/PrintHelperKitkat.java
index 0786763..89cc9e7 100644
--- a/v4/kitkat/android/support/v4/print/PrintHelperKitkat.java
+++ b/v4/kitkat/android/support/v4/print/PrintHelperKitkat.java
@@ -23,6 +23,7 @@
 import android.graphics.RectF;
 import android.graphics.pdf.PdfDocument.Page;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.CancellationSignal;
 import android.os.ParcelFileDescriptor;
@@ -42,11 +43,13 @@
 /**
  * Kitkat specific PrintManager API implementation.
  */
-public class PrintHelperKitkat {
+class PrintHelperKitkat {
     private static final String LOG_TAG = "PrintHelperKitkat";
     // will be <= 300 dpi on A4 (8.3×11.7) paper (worst case of 150 dpi)
     private final static int MAX_PRINT_SIZE = 3500;
     final Context mContext;
+    BitmapFactory.Options mDecodeOptions = null;
+    private final Object mLock = new Object();
     /**
      * image will be scaled but leave white space
      */
@@ -57,10 +60,19 @@
     public static final int SCALE_MODE_FILL = 2;
 
     /**
+     * select landscape (default)
+     */
+    public static final int ORIENTATION_LANDSCAPE = 1;
+
+    /**
+     * select portrait
+     */
+    public static final int ORIENTATION_PORTRAIT = 2;
+
+    /**
      * this is a black and white image
      */
     public static final int COLOR_MODE_MONOCHROME = 1;
-
     /**
      * this is a color image (default)
      */
@@ -70,12 +82,15 @@
 
     int mColorMode = COLOR_MODE_COLOR;
 
+    int mOrientation = ORIENTATION_LANDSCAPE;
+
     PrintHelperKitkat(Context context) {
         mContext = context;
     }
 
     /**
      * Selects whether the image will fill the paper and be cropped
+     * <p/>
      * {@link #SCALE_MODE_FIT}
      * or whether the image will be scaled but leave white space
      * {@link #SCALE_MODE_FILL}.
@@ -103,13 +118,33 @@
      * {@link #COLOR_MODE_MONOCHROME}.
      *
      * @param colorMode The color mode which is one of
-     * {@link #COLOR_MODE_COLOR} and {@link #COLOR_MODE_MONOCHROME}.
+     *                  {@link #COLOR_MODE_COLOR} and {@link #COLOR_MODE_MONOCHROME}.
      */
     public void setColorMode(int colorMode) {
         mColorMode = colorMode;
     }
 
     /**
+     * Sets whether to select landscape (default), {@link #ORIENTATION_LANDSCAPE}
+     * or portrait {@link #ORIENTATION_PORTRAIT}
+     * @param orientation The page orientation which is one of
+     *                    {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT}.
+     */
+    public void setOrientation(int orientation) {
+        mOrientation = orientation;
+    }
+
+    /**
+     * Gets the page orientation with which the image will be printed.
+     *
+     * @return The preferred orientation which is one of
+     * {@link #ORIENTATION_LANDSCAPE} or {@link #ORIENTATION_PORTRAIT}
+     */
+    public int getOrientation() {
+        return mOrientation;
+    }
+
+    /**
      * Gets the color mode with which the image will be printed.
      *
      * @return The color mode which is one of {@link #COLOR_MODE_COLOR}
@@ -171,23 +206,9 @@
                             Page page = pdfDocument.startPage(1);
 
                             RectF content = new RectF(page.getInfo().getContentRect());
-                            Matrix matrix = new Matrix();
 
-                            // Compute and apply scale to fill the page.
-                            float scale = content.width() / bitmap.getWidth();
-                            if (fittingMode == SCALE_MODE_FILL) {
-                                scale = Math.max(scale, content.height() / bitmap.getHeight());
-                            } else {
-                                scale = Math.min(scale, content.height() / bitmap.getHeight());
-                            }
-                            matrix.postScale(scale, scale);
-
-                            // Center the content.
-                            final float translateX = (content.width()
-                                    - bitmap.getWidth() * scale) / 2;
-                            final float translateY = (content.height()
-                                    - bitmap.getHeight() * scale) / 2;
-                            matrix.postTranslate(translateX, translateY);
+                            Matrix matrix = getMatrix(bitmap.getWidth(), bitmap.getHeight(),
+                                    content, fittingMode);
 
                             // Draw the bitmap.
                             page.getCanvas().drawBitmap(bitmap, matrix, null);
@@ -224,6 +245,36 @@
     }
 
     /**
+     * Calculates the transform the print an Image to fill the page
+     *
+     * @param imageWidth  with of bitmap
+     * @param imageHeight height of bitmap
+     * @param content     The output page dimensions
+     * @param fittingMode The mode of fitting {@link #SCALE_MODE_FILL} vs {@link #SCALE_MODE_FIT}
+     * @return Matrix to be used in canvas.drawBitmap(bitmap, matrix, null) call
+     */
+    private Matrix getMatrix(int imageWidth, int imageHeight, RectF content, int fittingMode) {
+        Matrix matrix = new Matrix();
+
+        // Compute and apply scale to fill the page.
+        float scale = content.width() / imageWidth;
+        if (fittingMode == SCALE_MODE_FILL) {
+            scale = Math.max(scale, content.height() / imageHeight);
+        } else {
+            scale = Math.min(scale, content.height() / imageHeight);
+        }
+        matrix.postScale(scale, scale);
+
+        // Center the content.
+        final float translateX = (content.width()
+                - imageWidth * scale) / 2;
+        final float translateY = (content.height()
+                - imageHeight * scale) / 2;
+        matrix.postTranslate(translateX, translateY);
+        return matrix;
+    }
+
+    /**
      * Prints an image located at the Uri. Image types supported are those of
      * <code>BitmapFactory.decodeStream</code> (JPEG, GIF, PNG, BMP, WEBP)
      *
@@ -231,9 +282,167 @@
      * @param imageFile The <code>Uri</code> pointing to an image to print.
      * @throws FileNotFoundException if <code>Uri</code> is not pointing to a valid image.
      */
-    public void printBitmap(String jobName, Uri imageFile) throws FileNotFoundException {
-        Bitmap bitmap = loadConstrainedBitmap(imageFile, MAX_PRINT_SIZE);
-        printBitmap(jobName, bitmap);
+    public void printBitmap(final String jobName, final Uri imageFile)
+            throws FileNotFoundException {
+        final int fittingMode = mScaleMode;
+
+        PrintDocumentAdapter printDocumentAdapter = new PrintDocumentAdapter() {
+            private PrintAttributes mAttributes;
+            AsyncTask<Uri, Boolean, Bitmap> loadBitmap;
+            Bitmap mBitmap = null;
+
+            @Override
+            public void onLayout(final PrintAttributes oldPrintAttributes,
+                                 final PrintAttributes newPrintAttributes,
+                                 final CancellationSignal cancellationSignal,
+                                 final LayoutResultCallback layoutResultCallback,
+                                 Bundle bundle) {
+                if (cancellationSignal.isCanceled()) {
+                    layoutResultCallback.onLayoutCancelled();
+                    mAttributes = newPrintAttributes;
+                    return;
+                }
+                // we finished the load
+                if (mBitmap != null) {
+                    PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName)
+                            .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO)
+                            .setPageCount(1)
+                            .build();
+                    boolean changed = !newPrintAttributes.equals(oldPrintAttributes);
+                    layoutResultCallback.onLayoutFinished(info, changed);
+                    return;
+                }
+
+                loadBitmap = new AsyncTask<Uri, Boolean, Bitmap>() {
+
+                    @Override
+                    protected void onPreExecute() {
+                        // First register for cancellation requests.
+                        cancellationSignal.setOnCancelListener(
+                                new CancellationSignal.OnCancelListener() {
+                                    @Override
+                                    public void onCancel() { // on different thread
+                                        cancelLoad();
+                                        cancel(false);
+                                    }
+                                });
+                    }
+
+                    @Override
+                    protected Bitmap doInBackground(Uri... uris) {
+                        try {
+                            return loadConstrainedBitmap(imageFile, MAX_PRINT_SIZE);
+                        } catch (FileNotFoundException e) {
+                          /* ignore */
+                        }
+                        return null;
+                    }
+
+                    @Override
+                    protected void onPostExecute(Bitmap bitmap) {
+                        super.onPostExecute(bitmap);
+                        mBitmap = bitmap;
+                        if (bitmap != null) {
+                            PrintDocumentInfo info = new PrintDocumentInfo.Builder(jobName)
+                                    .setContentType(PrintDocumentInfo.CONTENT_TYPE_PHOTO)
+                                    .setPageCount(1)
+                                    .build();
+                            boolean changed = !newPrintAttributes.equals(oldPrintAttributes);
+
+                            layoutResultCallback.onLayoutFinished(info, changed);
+
+                        } else {
+                            layoutResultCallback.onLayoutFailed(null);
+                        }
+                    }
+
+                    @Override
+                    protected void onCancelled(Bitmap result) {
+                        // Task was cancelled, report that.
+                        layoutResultCallback.onLayoutCancelled();
+                    }
+                };
+                loadBitmap.execute();
+
+                mAttributes = newPrintAttributes;
+            }
+
+            private void cancelLoad() {
+                synchronized (mLock) { // prevent race with set null below
+                    if (mDecodeOptions != null) {
+                        mDecodeOptions.requestCancelDecode();
+                        mDecodeOptions = null;
+                    }
+                }
+            }
+
+            @Override
+            public void onFinish() {
+                super.onFinish();
+                cancelLoad();
+                loadBitmap.cancel(true);
+            }
+
+            @Override
+            public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor fileDescriptor,
+                                CancellationSignal cancellationSignal,
+                                WriteResultCallback writeResultCallback) {
+                PrintedPdfDocument pdfDocument = new PrintedPdfDocument(mContext,
+                        mAttributes);
+                try {
+
+                    Page page = pdfDocument.startPage(1);
+                    RectF content = new RectF(page.getInfo().getContentRect());
+
+                    // Compute and apply scale to fill the page.
+                    Matrix matrix = getMatrix(mBitmap.getWidth(), mBitmap.getHeight(),
+                            content, fittingMode);
+
+                    // Draw the bitmap.
+                    page.getCanvas().drawBitmap(mBitmap, matrix, null);
+
+                    // Finish the page.
+                    pdfDocument.finishPage(page);
+
+                    try {
+                        // Write the document.
+                        pdfDocument.writeTo(new FileOutputStream(
+                                fileDescriptor.getFileDescriptor()));
+                        // Done.
+                        writeResultCallback.onWriteFinished(
+                                new PageRange[]{PageRange.ALL_PAGES});
+                    } catch (IOException ioe) {
+                        // Failed.
+                        Log.e(LOG_TAG, "Error writing printed content", ioe);
+                        writeResultCallback.onWriteFailed(null);
+                    }
+                } finally {
+                    if (pdfDocument != null) {
+                        pdfDocument.close();
+                    }
+                    if (fileDescriptor != null) {
+                        try {
+                            fileDescriptor.close();
+                        } catch (IOException ioe) {
+                            /* ignore */
+                        }
+                    }
+                }
+            }
+        };
+
+        PrintManager printManager = (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE);
+        PrintAttributes.Builder builder = new PrintAttributes.Builder();
+        builder.setColorMode(mColorMode);
+
+        if (mOrientation == ORIENTATION_LANDSCAPE) {
+            builder.setMediaSize(PrintAttributes.MediaSize.UNKNOWN_LANDSCAPE);
+        } else if (mOrientation == ORIENTATION_PORTRAIT) {
+            builder.setMediaSize(PrintAttributes.MediaSize.UNKNOWN_PORTRAIT);
+        }
+        PrintAttributes attr = builder.build();
+
+        printManager.print(jobName, printDocumentAdapter, attr);
     }
 
     /**
@@ -274,10 +483,20 @@
         if (sampleSize <= 0 || 0 >= (int) (Math.min(w, h) / sampleSize)) {
             return null;
         }
-        BitmapFactory.Options options = new BitmapFactory.Options();
-        options.inMutable = true;
-        options.inSampleSize = sampleSize;
-        return loadBitmap(uri, options);
+        BitmapFactory.Options decodeOptions = null;
+        synchronized (mLock) { // prevent race with set null below
+            mDecodeOptions = new BitmapFactory.Options();
+            mDecodeOptions.inMutable = true;
+            mDecodeOptions.inSampleSize = sampleSize;
+            decodeOptions = mDecodeOptions;
+        }
+        try {
+            return loadBitmap(uri, decodeOptions);
+        } finally {
+            synchronized (mLock) {
+                mDecodeOptions = null;
+            }
+        }
     }
 
     /**
diff --git a/v7/appcompat/res/layout-v11/abc_simple_decor.xml b/v7/appcompat/res/layout-v11/abc_simple_decor.xml
new file mode 100644
index 0000000..03a8f10
--- /dev/null
+++ b/v7/appcompat/res/layout-v11/abc_simple_decor.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<android.support.v7.internal.widget.NativeActionModeAwareLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/action_bar_root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:fitsSystemWindows="true">
+
+    <FrameLayout
+        android:id="@id/action_bar_activity_content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:foreground="?android:attr/windowContentOverlay"/>
+
+</android.support.v7.internal.widget.NativeActionModeAwareLayout>
diff --git a/v7/appcompat/res/layout/abc_simple_decor.xml b/v7/appcompat/res/layout/abc_simple_decor.xml
new file mode 100644
index 0000000..78316e8
--- /dev/null
+++ b/v7/appcompat/res/layout/abc_simple_decor.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/action_bar_root"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:fitsSystemWindows="true">
+
+    <FrameLayout
+        android:id="@id/action_bar_activity_content"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:foreground="?android:attr/windowContentOverlay"/>
+
+</LinearLayout>
diff --git a/v7/appcompat/res/values-large-v14/themes_base.xml b/v7/appcompat/res/values-large-v14/themes_base.xml
new file mode 100644
index 0000000..d898069
--- /dev/null
+++ b/v7/appcompat/res/values-large-v14/themes_base.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources>
+
+    <style name="Theme.Base.AppCompat.DialogWhenLarge"
+           parent="Theme.Base.AppCompat.DialogWhenLarge.Base" />
+
+    <style name="Theme.Base.AppCompat.Light.DialogWhenLarge"
+           parent="Theme.Base.AppCompat.Light.DialogWhenLarge.Base" />
+
+</resources>
diff --git a/v7/appcompat/res/values-large/dimens.xml b/v7/appcompat/res/values-large/dimens.xml
index dd9ecd9..de1cefc 100644
--- a/v7/appcompat/res/values-large/dimens.xml
+++ b/v7/appcompat/res/values-large/dimens.xml
@@ -22,4 +22,17 @@
      showAsAction="ifRoom" items can fit. "always" items can override this. -->
     <integer name="abc_max_action_buttons">4</integer>
 
+    <!-- The platform's desired fixed width for a dialog along the major axis
+         (the screen is in landscape). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_width_major">60%</item>
+    <!-- The platform's desired fixed width for a dialog along the minor axis
+         (the screen is in portrait). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_width_minor">90%</item>
+    <!-- The platform's desired fixed height for a dialog along the major axis
+         (the screen is in portrait). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_height_major">60%</item>
+    <!-- The platform's desired fixed height for a dialog along the minor axis
+         (the screen is in landscape). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_height_minor">90%</item>
+
 </resources>
diff --git a/v7/appcompat/res/values-large/themes_base.xml b/v7/appcompat/res/values-large/themes_base.xml
new file mode 100644
index 0000000..a19dcf0
--- /dev/null
+++ b/v7/appcompat/res/values-large/themes_base.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<resources>
+
+    <style name="Theme.Base.AppCompat.DialogWhenLarge"
+           parent="Theme.Base.AppCompat.Dialog.FixedSize" />
+
+    <style name="Theme.Base.AppCompat.Light.DialogWhenLarge"
+           parent="Theme.Base.AppCompat.Dialog.Light.FixedSize" />
+
+</resources>
diff --git a/v7/appcompat/res/values-v11/themes_base.xml b/v7/appcompat/res/values-v11/themes_base.xml
index ca7acbd..c74b4f3 100644
--- a/v7/appcompat/res/values-v11/themes_base.xml
+++ b/v7/appcompat/res/values-v11/themes_base.xml
@@ -49,4 +49,31 @@
         <item name="selectableItemBackground">?android:attr/selectableItemBackground</item>
     </style>
 
+    <style name="Theme.Base.AppCompat.Dialog.FixedSize" parent="android:Theme.Holo.Dialog">
+        <item name="windowFixedWidthMajor">@dimen/dialog_fixed_width_major</item>
+        <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
+        <item name="windowFixedHeightMajor">@dimen/dialog_fixed_height_major</item>
+        <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
+        <item name="windowActionBar">false</item>
+
+        <!-- Attributes populated from the framework to be read by apps -->
+        <item name="buttonBarStyle">?android:attr/buttonBarStyle</item>
+        <item name="buttonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
+        <item name="selectableItemBackground">?android:attr/selectableItemBackground</item>
+    </style>
+
+    <style name="Theme.Base.AppCompat.Dialog.Light.FixedSize"
+           parent="android:Theme.Holo.Light.Dialog">
+        <item name="windowFixedWidthMajor">@dimen/dialog_fixed_width_major</item>
+        <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
+        <item name="windowFixedHeightMajor">@dimen/dialog_fixed_height_major</item>
+        <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
+        <item name="windowActionBar">false</item>
+
+        <!-- Attributes populated from the framework to be read by apps -->
+        <item name="buttonBarStyle">?android:attr/buttonBarStyle</item>
+        <item name="buttonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
+        <item name="selectableItemBackground">?android:attr/selectableItemBackground</item>
+    </style>
+
 </resources>
diff --git a/v7/appcompat/res/values-v14/styles_base.xml b/v7/appcompat/res/values-v14/styles_base.xml
index 4c64aee..b76b87b 100644
--- a/v7/appcompat/res/values-v14/styles_base.xml
+++ b/v7/appcompat/res/values-v14/styles_base.xml
@@ -77,10 +77,6 @@
            parent="android:Widget.Holo.Light.ActionBar.TabText.Inverse">
     </style>
 
-    <style name="Widget.AppCompat.Light.Base.ActionMode.Inverse"
-           parent="android:Widget.Holo.Light.ActionMode.Inverse">
-    </style>
-
     <style name="TextAppearance.AppCompat.Widget.Base.ActionBar.Menu"
            parent="android:TextAppearance.Holo.Widget.ActionBar.Menu">
     </style>
@@ -101,6 +97,16 @@
            parent="android:TextAppearance.Holo.Widget.ActionBar.Subtitle.Inverse">
     </style>
 
+    <style name="Widget.AppCompat.Base.ActionMode" parent="android:Widget.Holo.ActionMode">
+    </style>
+
+    <style name="Widget.AppCompat.Light.Base.ActionMode" parent="android:Widget.Holo.Light.ActionMode">
+    </style>
+
+    <style name="Widget.AppCompat.Light.Base.ActionMode.Inverse"
+           parent="android:Widget.Holo.Light.ActionMode.Inverse">
+    </style>
+
     <style name="TextAppearance.AppCompat.Widget.Base.ActionMode.Title"
            parent="android:TextAppearance.Holo.Widget.ActionMode.Title">
     </style>
diff --git a/v7/appcompat/res/values-v14/themes_base.xml b/v7/appcompat/res/values-v14/themes_base.xml
index 26ad271..75c4ee7 100644
--- a/v7/appcompat/res/values-v14/themes_base.xml
+++ b/v7/appcompat/res/values-v14/themes_base.xml
@@ -106,4 +106,69 @@
         <item name="buttonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
     </style>
 
+    <style name="Theme.Base.AppCompat.DialogWhenLarge"
+           parent="Theme.Base.AppCompat.DialogWhenLarge.Base" />
+
+    <style name="Theme.Base.AppCompat.Light.DialogWhenLarge"
+           parent="Theme.Base.AppCompat.Light.DialogWhenLarge.Base" />
+
+    <!--
+        As we have defined the theme in values-large (for compat) and values-large takes precedence
+        over values-v14, we need to reset back to the Holo parent in values-large-v14. As the themes
+        in values-v14 & values-large-v14 are exactly the same, these "double base" themes can be
+        inherited from in both values-v14 and values-large-v14.
+    -->
+
+    <style name="Theme.Base.AppCompat.DialogWhenLarge.Base"
+           parent="android:Theme.Holo.DialogWhenLarge">
+        <!-- Copy system flag values for our use -->
+        <item name="windowActionBar">?android:attr/windowActionBar</item>
+        <item name="actionBarSize">?android:attr/actionBarSize</item>
+        <item name="actionBarItemBackground">?android:attr/actionBarItemBackground</item>
+        <item name="selectableItemBackground">?android:attr/selectableItemBackground</item>
+        <item name="actionButtonStyle">?android:attr/actionButtonStyle</item>
+        <item name="dividerVertical">?android:attr/dividerVertical</item>
+        <item name="dividerHorizontal">?android:attr/dividerHorizontal</item>
+        <item name="actionBarWidgetTheme">@null</item>
+        <item name="android:actionBarWidgetTheme">?attr/actionBarWidgetTheme</item>
+
+        <!-- Required for use of support_simple_spinner_dropdown_item.xml -->
+        <item name="listPreferredItemHeight">?android:attr/listPreferredItemHeight</item>
+        <item name="listPreferredItemHeightSmall">?android:attr/listPreferredItemHeightSmall</item>
+        <item name="listPreferredItemHeightLarge">?android:attr/listPreferredItemHeightLarge</item>
+        <item name="listPreferredItemPaddingLeft">?android:attr/listPreferredItemPaddingLeft</item>
+        <item name="listPreferredItemPaddingRight">?android:attr/listPreferredItemPaddingRight
+        </item>
+
+        <!-- Attributes populated from the framework to be read by apps -->
+        <item name="buttonBarStyle">?android:attr/buttonBarStyle</item>
+        <item name="buttonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
+    </style>
+
+    <style name="Theme.Base.AppCompat.Light.DialogWhenLarge.Base"
+           parent="android:Theme.Holo.Light.DialogWhenLarge">
+        <!-- Copy system flag values for our use -->
+        <item name="windowActionBar">?android:attr/windowActionBar</item>
+        <item name="actionBarSize">?android:attr/actionBarSize</item>
+        <item name="actionBarItemBackground">?android:attr/actionBarItemBackground</item>
+        <item name="selectableItemBackground">?android:attr/selectableItemBackground</item>
+        <item name="actionButtonStyle">?android:attr/actionButtonStyle</item>
+        <item name="dividerVertical">?android:attr/dividerVertical</item>
+        <item name="dividerHorizontal">?android:attr/dividerHorizontal</item>
+        <item name="actionBarWidgetTheme">@null</item>
+        <item name="android:actionBarWidgetTheme">?attr/actionBarWidgetTheme</item>
+
+        <!-- Required for use of support_simple_spinner_dropdown_item.xml -->
+        <item name="listPreferredItemHeight">?android:attr/listPreferredItemHeight</item>
+        <item name="listPreferredItemHeightSmall">?android:attr/listPreferredItemHeightSmall</item>
+        <item name="listPreferredItemHeightLarge">?android:attr/listPreferredItemHeightLarge</item>
+        <item name="listPreferredItemPaddingLeft">?android:attr/listPreferredItemPaddingLeft</item>
+        <item name="listPreferredItemPaddingRight">?android:attr/listPreferredItemPaddingRight
+        </item>
+
+        <!-- Attributes populated from the framework to be read by apps -->
+        <item name="buttonBarStyle">?android:attr/buttonBarStyle</item>
+        <item name="buttonBarButtonStyle">?android:attr/buttonBarButtonStyle</item>
+    </style>
+
 </resources>
diff --git a/v7/appcompat/res/values-xlarge/dimens.xml b/v7/appcompat/res/values-xlarge/dimens.xml
index 6217586..4172442 100644
--- a/v7/appcompat/res/values-xlarge/dimens.xml
+++ b/v7/appcompat/res/values-xlarge/dimens.xml
@@ -39,4 +39,17 @@
     <!-- Minimum width of the search view text entry area. -->
     <dimen name="abc_search_view_text_min_width">192dip</dimen>
 
+    <!-- The platform's desired fixed width for a dialog along the major axis
+         (the screen is in landscape). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_width_major">50%</item>
+    <!-- The platform's desired fixed width for a dialog along the minor axis
+         (the screen is in portrait). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_width_minor">70%</item>
+    <!-- The platform's desired fixed height for a dialog along the major axis
+         (the screen is in portrait). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_height_major">60%</item>
+    <!-- The platform's desired fixed height for a dialog along the minor axis
+         (the screen is in landscape). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_height_minor">90%</item>
+
 </resources>
diff --git a/v7/appcompat/res/values/attrs.xml b/v7/appcompat/res/values/attrs.xml
index 89749c0..e0c8465 100644
--- a/v7/appcompat/res/values/attrs.xml
+++ b/v7/appcompat/res/values/attrs.xml
@@ -32,6 +32,25 @@
         <attr name="windowActionBar" format="boolean"/>
         <attr name="windowActionBarOverlay" format="boolean"/>
         <attr name="windowSplitActionBar" format="boolean" />
+
+        <!-- A fixed width for the window along the major axis of the screen,
+             that is, when in landscape. Can be either an absolute dimension
+             or a fraction of the screen size in that dimension. -->
+        <attr name="windowFixedWidthMajor" format="dimension|fraction" />
+        <!-- A fixed height for the window along the minor axis of the screen,
+             that is, when in landscape. Can be either an absolute dimension
+             or a fraction of the screen size in that dimension. -->
+        <attr name="windowFixedHeightMinor" format="dimension|fraction" />
+
+        <!-- A fixed width for the window along the minor axis of the screen,
+             that is, when in portrait. Can be either an absolute dimension
+             or a fraction of the screen size in that dimension. -->
+        <attr name="windowFixedWidthMinor" format="dimension|fraction" />
+        <!-- A fixed height for the window along the major axis of the screen,
+             that is, when in portrait. Can be either an absolute dimension
+             or a fraction of the screen size in that dimension. -->
+        <attr name="windowFixedHeightMajor" format="dimension|fraction" />
+
     </declare-styleable>
 
     <!-- ============================================ -->
diff --git a/v7/appcompat/res/values/dimens.xml b/v7/appcompat/res/values/dimens.xml
index befb9f6..c2cf3a3 100644
--- a/v7/appcompat/res/values/dimens.xml
+++ b/v7/appcompat/res/values/dimens.xml
@@ -58,4 +58,18 @@
     <!-- Width of the icon in a dropdown list -->
     <dimen name="abc_dropdownitem_icon_width">32dip</dimen>
 
+
+    <!-- The platform's desired fixed width for a dialog along the major axis
+         (the screen is in landscape). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_width_major">320dp</item>
+    <!-- The platform's desired fixed width for a dialog along the minor axis
+         (the screen is in portrait). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_width_minor">320dp</item>
+    <!-- The platform's desired fixed height for a dialog along the major axis
+         (the screen is in portrait). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_height_major">80%</item>
+    <!-- The platform's desired fixed height for a dialog along the minor axis
+         (the screen is in landscape). This may be either a fraction or a dimension.-->
+    <item type="dimen" name="dialog_fixed_height_minor">100%</item>
+
 </resources>
diff --git a/v7/appcompat/res/values/styles.xml b/v7/appcompat/res/values/styles.xml
index 94d2e88..2c54ea5 100644
--- a/v7/appcompat/res/values/styles.xml
+++ b/v7/appcompat/res/values/styles.xml
@@ -126,6 +126,9 @@
     <style name="Widget.AppCompat.ActionMode" parent="Widget.AppCompat.Base.ActionMode">
     </style>
 
+    <style name="Widget.AppCompat.Light.ActionMode" parent="Widget.AppCompat.Light.Base.ActionMode">
+    </style>
+
     <style name="Widget.AppCompat.Light.ActionMode.Inverse"
            parent="Widget.AppCompat.Light.Base.ActionMode.Inverse">
     </style>
diff --git a/v7/appcompat/res/values/styles_base.xml b/v7/appcompat/res/values/styles_base.xml
index 79dd732..5771bb0 100644
--- a/v7/appcompat/res/values/styles_base.xml
+++ b/v7/appcompat/res/values/styles_base.xml
@@ -172,6 +172,9 @@
         </item>
     </style>
 
+    <style name="Widget.AppCompat.Light.Base.ActionMode" parent="Widget.AppCompat.Base.ActionMode">
+    </style>
+
     <style name="Widget.AppCompat.Light.Base.ActionMode.Inverse"
            parent="Widget.AppCompat.Base.ActionMode">
         <item name="titleTextStyle">
diff --git a/v7/appcompat/res/values/themes.xml b/v7/appcompat/res/values/themes.xml
index 7199f77..f761155 100644
--- a/v7/appcompat/res/values/themes.xml
+++ b/v7/appcompat/res/values/themes.xml
@@ -181,6 +181,13 @@
 
     </style>
 
+    <style name="Theme.AppCompat.DialogWhenLarge"
+           parent="Theme.Base.AppCompat.DialogWhenLarge">
+    </style>
+
+    <style name="Theme.AppCompat.Light.DialogWhenLarge"
+           parent="Theme.Base.AppCompat.Light.DialogWhenLarge">
+    </style>
 
     <!-- Menu/item attributes -->
     <style name="Theme.AppCompat.CompactMenu" parent="Theme.AppCompat.Base.CompactMenu">
diff --git a/v7/appcompat/res/values/themes_base.xml b/v7/appcompat/res/values/themes_base.xml
index 3b514a8..7d62bc9 100644
--- a/v7/appcompat/res/values/themes_base.xml
+++ b/v7/appcompat/res/values/themes_base.xml
@@ -131,7 +131,7 @@
         <item name="actionMenuTextColor">?android:attr/textColorPrimaryDisableOnly</item>
 
         <!-- Action Mode -->
-        <item name="actionModeStyle">@style/Widget.AppCompat.ActionMode</item>
+        <item name="actionModeStyle">@style/Widget.AppCompat.Light.ActionMode</item>
         <item name="actionModeBackground">@drawable/abc_cab_background_top_holo_light</item>
         <item name="actionModeSplitBackground">@drawable/abc_cab_background_bottom_holo_light</item>
         <item name="actionModeCloseDrawable">@drawable/abc_ic_cab_done_holo_light</item>
@@ -198,4 +198,56 @@
         <item name="android:listViewStyle">@android:style/Widget.ListView.Menu</item>
     </style>
 
+    <style name="Theme.Base.AppCompat.DialogWhenLarge"
+           parent="Theme.Base.AppCompat">
+    </style>
+
+    <style name="Theme.Base.AppCompat.Light.DialogWhenLarge"
+           parent="Theme.Base.AppCompat.Light">
+    </style>
+
+    <style name="Theme.Base.AppCompat.Dialog.FixedSize" parent="android:Theme.Dialog">
+        <item name="windowFixedWidthMajor">@dimen/dialog_fixed_width_major</item>
+        <item name="windowFixedWidthMinor">@dimen/dialog_fixed_width_minor</item>
+        <item name="windowFixedHeightMajor">@dimen/dialog_fixed_height_major</item>
+        <item name="windowFixedHeightMinor">@dimen/dialog_fixed_height_minor</item>
+
+        <item name="windowActionBar">true</item>
+        <!-- Remove system title bars; we will add the action bar ourselves. -->
+        <item name="android:windowNoTitle">true</item>
+
+        <item name="buttonBarStyle">@android:style/ButtonBar</item>
+        <item name="buttonBarButtonStyle">@android:style/Widget.Button</item>
+        <item name="selectableItemBackground">@drawable/abc_item_background_holo_dark</item>
+
+        <item name="dividerVertical">@drawable/abc_list_divider_holo_dark</item>
+        <item name="dividerHorizontal">@drawable/abc_list_divider_holo_dark</item>
+
+        <item name="listPreferredItemHeight">?android:attr/listPreferredItemHeight</item>
+        <item name="listPreferredItemHeightSmall">48dp</item>
+        <item name="listPreferredItemHeightLarge">80dp</item>
+        <item name="listPreferredItemPaddingLeft">8dip</item>
+        <item name="listPreferredItemPaddingRight">8dip</item>
+
+        <item name="textAppearanceListItem">?android:attr/textAppearanceMedium</item>
+        <item name="textAppearanceListItemSmall">?android:attr/textAppearanceMedium</item>
+
+        <!-- Action Mode -->
+        <item name="actionModeStyle">@style/Widget.AppCompat.ActionMode</item>
+        <item name="actionModeBackground">@drawable/abc_cab_background_top_holo_dark</item>
+        <item name="actionModeSplitBackground">@drawable/abc_cab_background_bottom_holo_dark</item>
+        <item name="actionModeCloseDrawable">@drawable/abc_ic_cab_done_holo_dark</item>
+        <item name="actionModeCloseButtonStyle">@style/Widget.AppCompat.ActionButton.CloseMode
+        </item>
+
+        <!-- Panel attributes -->
+        <item name="panelMenuListWidth">@dimen/abc_panel_menu_list_width</item>
+        <item name="panelMenuListTheme">@style/Theme.AppCompat.CompactMenu</item>
+        <item name="android:panelBackground">@drawable/abc_menu_hardkey_panel_holo_dark</item>
+        <item name="listChoiceBackgroundIndicator">@drawable/abc_list_selector_holo_dark</item>
+    </style>
+
+    <style name="Theme.Base.AppCompat.Dialog.Light.FixedSize"
+           parent="Theme.Base.AppCompat.Dialog.FixedSize" />
+
 </resources>
diff --git a/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java b/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java
index d0fa8a5..8670f94 100644
--- a/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java
+++ b/v7/appcompat/src/android/support/v7/app/ActionBarActivityDelegateBase.java
@@ -20,6 +20,7 @@
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
 import android.support.v4.app.ActionBarDrawerToggle;
 import android.support.v4.view.WindowCompat;
 import android.support.v7.appcompat.R;
@@ -33,11 +34,15 @@
 import android.support.v7.internal.widget.ActionBarView;
 import android.support.v7.internal.widget.ProgressBarICS;
 import android.support.v7.view.ActionMode;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
+import android.view.WindowManager;
 import android.widget.FrameLayout;
 
 class ActionBarActivityDelegateBase extends ActionBarActivityDelegate implements
@@ -62,21 +67,11 @@
     // Used to keep track of Progress Bar Window features
     private boolean mFeatureProgress, mFeatureIndeterminateProgress;
 
-    private boolean mInvalidateMenuPosted;
-    private final Runnable mInvalidateMenuRunnable = new Runnable() {
-        @Override
-        public void run() {
-            final MenuBuilder menu = createMenu();
-            if (mActivity.superOnCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu) &&
-                    mActivity.superOnPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, menu)) {
-                setMenu(menu);
-            } else {
-                setMenu(null);
-            }
-
-            mInvalidateMenuPosted = false;
-        }
-    };
+    // Used for emulating PanelFeatureState
+    private boolean mClosingActionMenu;
+    private boolean mPanelIsPrepared;
+    private boolean mPanelRefreshContent;
+    private Bundle mPanelFrozenActionViewState;
 
     ActionBarActivityDelegateBase(ActionBarActivity activity) {
         super(activity);
@@ -119,51 +114,35 @@
     @Override
     public void setContentView(View v) {
         ensureSubDecor();
-        if (mHasActionBar) {
-            ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content);
-            contentParent.removeAllViews();
-            contentParent.addView(v);
-        } else {
-            mActivity.superSetContentView(v);
-        }
+        ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content);
+        contentParent.removeAllViews();
+        contentParent.addView(v);
         mActivity.onSupportContentChanged();
     }
 
     @Override
     public void setContentView(int resId) {
         ensureSubDecor();
-        if (mHasActionBar) {
-            ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content);
-            contentParent.removeAllViews();
-            mActivity.getLayoutInflater().inflate(resId, contentParent);
-        } else {
-            mActivity.superSetContentView(resId);
-        }
+        ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content);
+        contentParent.removeAllViews();
+        mActivity.getLayoutInflater().inflate(resId, contentParent);
         mActivity.onSupportContentChanged();
     }
 
     @Override
     public void setContentView(View v, ViewGroup.LayoutParams lp) {
         ensureSubDecor();
-        if (mHasActionBar) {
-            ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content);
-            contentParent.removeAllViews();
-            contentParent.addView(v, lp);
-        } else {
-            mActivity.superSetContentView(v, lp);
-        }
+        ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content);
+        contentParent.removeAllViews();
+        contentParent.addView(v, lp);
         mActivity.onSupportContentChanged();
     }
 
     @Override
     public void addContentView(View v, ViewGroup.LayoutParams lp) {
         ensureSubDecor();
-        if (mHasActionBar) {
-            ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content);
-            contentParent.addView(v, lp);
-        } else {
-            mActivity.superSetContentView(v, lp);
-        }
+        ViewGroup contentParent = (ViewGroup) mActivity.findViewById(android.R.id.content);
+        contentParent.addView(v, lp);
         mActivity.onSupportContentChanged();
     }
 
@@ -173,54 +152,58 @@
     }
 
     final void ensureSubDecor() {
-        if (mHasActionBar && !mSubDecorInstalled) {
-            if (mOverlayActionBar) {
-                mActivity.superSetContentView(R.layout.abc_action_bar_decor_overlay);
+        if (!mSubDecorInstalled) {
+            if (mHasActionBar) {
+                if (mOverlayActionBar) {
+                    mActivity.superSetContentView(R.layout.abc_action_bar_decor_overlay);
+                } else {
+                    mActivity.superSetContentView(R.layout.abc_action_bar_decor);
+                }
+                mActionBarView = (ActionBarView) mActivity.findViewById(R.id.action_bar);
+                mActionBarView.setWindowCallback(mActivity);
+
+                /**
+                 * Progress Bars
+                 */
+                if (mFeatureProgress) {
+                    mActionBarView.initProgress();
+                }
+                if (mFeatureIndeterminateProgress) {
+                    mActionBarView.initIndeterminateProgress();
+                }
+
+                /**
+                 * Split Action Bar
+                 */
+                boolean splitWhenNarrow = UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW
+                        .equals(getUiOptionsFromMetadata());
+                boolean splitActionBar;
+
+                if (splitWhenNarrow) {
+                    splitActionBar = mActivity.getResources()
+                            .getBoolean(R.bool.abc_split_action_bar_is_narrow);
+                } else {
+                    TypedArray a = mActivity.obtainStyledAttributes(R.styleable.ActionBarWindow);
+                    splitActionBar = a
+                            .getBoolean(R.styleable.ActionBarWindow_windowSplitActionBar, false);
+                    a.recycle();
+                }
+
+                final ActionBarContainer splitView = (ActionBarContainer) mActivity.findViewById(
+                        R.id.split_action_bar);
+                if (splitView != null) {
+                    mActionBarView.setSplitView(splitView);
+                    mActionBarView.setSplitActionBar(splitActionBar);
+                    mActionBarView.setSplitWhenNarrow(splitWhenNarrow);
+
+                    final ActionBarContextView cab = (ActionBarContextView) mActivity.findViewById(
+                            R.id.action_context_bar);
+                    cab.setSplitView(splitView);
+                    cab.setSplitActionBar(splitActionBar);
+                    cab.setSplitWhenNarrow(splitWhenNarrow);
+                }
             } else {
-                mActivity.superSetContentView(R.layout.abc_action_bar_decor);
-            }
-            mActionBarView = (ActionBarView) mActivity.findViewById(R.id.action_bar);
-            mActionBarView.setWindowCallback(mActivity);
-
-            /**
-             * Progress Bars
-             */
-            if (mFeatureProgress) {
-                mActionBarView.initProgress();
-            }
-            if (mFeatureIndeterminateProgress) {
-                mActionBarView.initIndeterminateProgress();
-            }
-
-            /**
-             * Split Action Bar
-             */
-            boolean splitWhenNarrow = UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW
-                    .equals(getUiOptionsFromMetadata());
-            boolean splitActionBar;
-
-            if (splitWhenNarrow) {
-                splitActionBar = mActivity.getResources()
-                        .getBoolean(R.bool.abc_split_action_bar_is_narrow);
-            } else {
-                TypedArray a = mActivity.obtainStyledAttributes(R.styleable.ActionBarWindow);
-                splitActionBar = a
-                        .getBoolean(R.styleable.ActionBarWindow_windowSplitActionBar, false);
-                a.recycle();
-            }
-
-            final ActionBarContainer splitView = (ActionBarContainer) mActivity.findViewById(
-                    R.id.split_action_bar);
-            if (splitView != null) {
-                mActionBarView.setSplitView(splitView);
-                mActionBarView.setSplitActionBar(splitActionBar);
-                mActionBarView.setSplitWhenNarrow(splitWhenNarrow);
-
-                final ActionBarContextView cab = (ActionBarContextView) mActivity.findViewById(
-                        R.id.action_context_bar);
-                cab.setSplitView(splitView);
-                cab.setSplitActionBar(splitActionBar);
-                cab.setSplitWhenNarrow(splitWhenNarrow);
+                mActivity.superSetContentView(R.layout.abc_simple_decor);
             }
 
             // Change our content FrameLayout to use the android.R.id.content id.
@@ -233,14 +216,78 @@
             // A title was set before we've install the decor so set it now.
             if (mTitleToSet != null) {
                 mActionBarView.setWindowTitle(mTitleToSet);
-                mTitleToSet  = null;
+                mTitleToSet = null;
             }
 
+            applyFixedSizeWindow();
+
             mSubDecorInstalled = true;
-            supportInvalidateOptionsMenu();
+
+            // Post supportInvalidateOptionsMenu() so that the menu is invalidated post-onCreate()
+            mActivity.getWindow().getDecorView().post(new Runnable() {
+                @Override
+                public void run() {
+                    supportInvalidateOptionsMenu();
+                }
+            });
         }
     }
 
+    private void applyFixedSizeWindow() {
+        TypedArray a = mActivity.obtainStyledAttributes(R.styleable.ActionBarWindow);
+
+        TypedValue mFixedWidthMajor = null;
+        TypedValue mFixedWidthMinor = null;
+        TypedValue mFixedHeightMajor = null;
+        TypedValue mFixedHeightMinor = null;
+
+        if (a.hasValue(R.styleable.ActionBarWindow_windowFixedWidthMajor)) {
+            if (mFixedWidthMajor == null) mFixedWidthMajor = new TypedValue();
+            a.getValue(R.styleable.ActionBarWindow_windowFixedWidthMajor, mFixedWidthMajor);
+        }
+        if (a.hasValue(R.styleable.ActionBarWindow_windowFixedWidthMinor)) {
+            if (mFixedWidthMinor == null) mFixedWidthMinor = new TypedValue();
+            a.getValue(R.styleable.ActionBarWindow_windowFixedWidthMinor, mFixedWidthMinor);
+        }
+        if (a.hasValue(R.styleable.ActionBarWindow_windowFixedHeightMajor)) {
+            if (mFixedHeightMajor == null) mFixedHeightMajor = new TypedValue();
+            a.getValue(R.styleable.ActionBarWindow_windowFixedHeightMajor, mFixedHeightMajor);
+        }
+        if (a.hasValue(R.styleable.ActionBarWindow_windowFixedHeightMinor)) {
+            if (mFixedHeightMinor == null) mFixedHeightMinor = new TypedValue();
+            a.getValue(R.styleable.ActionBarWindow_windowFixedHeightMinor, mFixedHeightMinor);
+        }
+
+        final DisplayMetrics metrics = mActivity.getResources().getDisplayMetrics();
+        final boolean isPortrait = metrics.widthPixels < metrics.heightPixels;
+        int w = ViewGroup.LayoutParams.MATCH_PARENT;
+        int h = ViewGroup.LayoutParams.MATCH_PARENT;
+
+        final TypedValue tvw = isPortrait ? mFixedWidthMinor : mFixedWidthMajor;
+        if (tvw != null && tvw.type != TypedValue.TYPE_NULL) {
+            if (tvw.type == TypedValue.TYPE_DIMENSION) {
+                w = (int) tvw.getDimension(metrics);
+            } else if (tvw.type == TypedValue.TYPE_FRACTION) {
+                w = (int) tvw.getFraction(metrics.widthPixels, metrics.widthPixels);
+            }
+        }
+
+        final TypedValue tvh = isPortrait ? mFixedHeightMajor : mFixedHeightMinor;
+        if (tvh != null && tvh.type != TypedValue.TYPE_NULL) {
+            if (tvh.type == TypedValue.TYPE_DIMENSION) {
+                h = (int) tvh.getDimension(metrics);
+            } else if (tvh.type == TypedValue.TYPE_FRACTION) {
+                h = (int) tvh.getFraction(metrics.heightPixels, metrics.heightPixels);
+            }
+        }
+
+        if (w != ViewGroup.LayoutParams.MATCH_PARENT || h != ViewGroup.LayoutParams.MATCH_PARENT) {
+            mActivity.getWindow().setLayout(w, h);
+        }
+
+        a.recycle();
+    }
+
     @Override
     public boolean supportRequestWindowFeature(int featureId) {
         switch (featureId) {
@@ -274,42 +321,8 @@
     public View onCreatePanelView(int featureId) {
         View createdPanelView = null;
 
-        if (featureId == Window.FEATURE_OPTIONS_PANEL) {
-            boolean show = true;
-            MenuBuilder menu = mMenu;
-
-            if (mActionMode == null) {
-                // We only want to dispatch Activity/Fragment menu calls if there isn't
-                // currently an action mode
-
-                if (menu == null) {
-                    // We don't have a menu created, so create one
-                    menu = createMenu();
-                    setMenu(menu);
-
-                    // Make sure we're not dispatching item changes to presenters
-                    menu.stopDispatchingItemsChanged();
-                    // Dispatch onCreateOptionsMenu
-                    show = mActivity.superOnCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, menu);
-                }
-
-                if (show) {
-                    // Make sure we're not dispatching item changes to presenters
-                    menu.stopDispatchingItemsChanged();
-                    // Dispatch onPrepareOptionsMenu
-                    show = mActivity.superOnPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, menu);
-                }
-            }
-
-            if (show) {
-                createdPanelView = (View) getListMenuView(mActivity, this);
-
-                // Allow menu to start dispatching changes to presenters
-                menu.startDispatchingItemsChanged();
-            } else {
-                // If the menu isn't being shown, we no longer need it
-                setMenu(null);
-            }
+        if (featureId == Window.FEATURE_OPTIONS_PANEL && preparePanel()) {
+            createdPanelView = (View) getListMenuView(mActivity, this);
         }
 
         return createdPanelView;
@@ -351,7 +364,13 @@
 
     @Override
     public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
+        if (mClosingActionMenu) {
+            return;
+        }
+        mClosingActionMenu = true;
         mActivity.closeOptionsMenu();
+        mActionBarView.dismissPopupMenus();
+        mClosingActionMenu = false;
     }
 
     @Override
@@ -384,16 +403,23 @@
 
     @Override
     public void supportInvalidateOptionsMenu() {
-        if (!mInvalidateMenuPosted) {
-            mInvalidateMenuPosted = true;
-            mActivity.getWindow().getDecorView().post(mInvalidateMenuRunnable);
+        if (mMenu != null) {
+            Bundle savedActionViewStates = new Bundle();
+            mMenu.saveActionViewStates(savedActionViewStates);
+            if (savedActionViewStates.size() > 0) {
+                mPanelFrozenActionViewState = savedActionViewStates;
+            }
+            // This will be started again when the panel is prepared.
+            mMenu.stopDispatchingItemsChanged();
+            mMenu.clear();
         }
-    }
+        mPanelRefreshContent = true;
 
-    private MenuBuilder createMenu() {
-        MenuBuilder menu = new MenuBuilder(getActionBarThemedContext());
-        menu.setCallback(this);
-        return menu;
+        // Prepare the options panel if we have an action bar
+        if (mActionBarView != null) {
+            mPanelIsPrepared = false;
+            preparePanel();
+        }
     }
 
     private void reopenMenu(MenuBuilder menu, boolean toggleMenuMode) {
@@ -435,25 +461,6 @@
         return mListMenuPresenter.getMenuView(new FrameLayout(context));
     }
 
-    private void setMenu(MenuBuilder menu) {
-        if (menu == mMenu) {
-            return;
-        }
-
-        if (mMenu != null) {
-            mMenu.removeMenuPresenter(mListMenuPresenter);
-        }
-        mMenu = menu;
-
-        if (menu != null && mListMenuPresenter != null) {
-            // Only update list menu if there isn't an action mode menu
-            menu.addMenuPresenter(mListMenuPresenter);
-        }
-        if (mActionBarView != null) {
-            mActionBarView.setMenu(menu, this);
-        }
-    }
-
     @Override
     public boolean onBackPressed() {
         // Back cancels action modes first.
@@ -578,6 +585,80 @@
         return pb;
     }
 
+    private boolean initializePanelMenu() {
+        mMenu = new MenuBuilder(getActionBarThemedContext());
+        mMenu.setCallback(this);
+        return true;
+    }
+
+    private boolean preparePanel() {
+        // Already prepared (isPrepared will be reset to false later)
+        if (mPanelIsPrepared) {
+            return true;
+        }
+
+        // Init the panel state's menu--return false if init failed
+        if (mMenu == null || mPanelRefreshContent) {
+            if (mMenu == null) {
+                if (!initializePanelMenu() || (mMenu == null)) {
+                    return false;
+                }
+            }
+
+            if (mActionBarView != null) {
+                mActionBarView.setMenu(mMenu, this);
+            }
+
+            // Creating the panel menu will involve a lot of manipulation;
+            // don't dispatch change events to presenters until we're done.
+            mMenu.stopDispatchingItemsChanged();
+
+            // Call callback, and return if it doesn't want to display menu.
+            if (!mActivity.superOnCreatePanelMenu(Window.FEATURE_OPTIONS_PANEL, mMenu)) {
+                // Ditch the menu created above
+                mMenu = null;
+
+                if (mActionBarView != null) {
+                    // Don't show it in the action bar either
+                    mActionBarView.setMenu(null, this);
+                }
+
+                return false;
+            }
+
+            mPanelRefreshContent = false;
+        }
+
+        // Preparing the panel menu can involve a lot of manipulation;
+        // don't dispatch change events to presenters until we're done.
+        mMenu.stopDispatchingItemsChanged();
+
+        // Restore action view state before we prepare. This gives apps
+        // an opportunity to override frozen/restored state in onPrepare.
+        if (mPanelFrozenActionViewState != null) {
+            mMenu.restoreActionViewStates(mPanelFrozenActionViewState);
+            mPanelFrozenActionViewState = null;
+        }
+
+        // Callback and return if the callback does not want to show the menu
+        if (!mActivity.superOnPreparePanel(Window.FEATURE_OPTIONS_PANEL, null, mMenu)) {
+            if (mActionBarView != null) {
+                // The app didn't want to show the menu for now but it still exists.
+                // Clear it out of the action bar.
+                mActionBarView.setMenu(null, this);
+            }
+            mMenu.startDispatchingItemsChanged();
+            return false;
+        }
+
+        mMenu.startDispatchingItemsChanged();
+
+        // Set other state
+        mPanelIsPrepared = true;
+
+        return true;
+    }
+
     /**
      * Clears out internal reference when the action mode is destroyed.
      */
diff --git a/v7/appcompat/src/android/support/v7/internal/widget/ListPopupWindow.java b/v7/appcompat/src/android/support/v7/internal/widget/ListPopupWindow.java
index 8913fea..35299f8 100644
--- a/v7/appcompat/src/android/support/v7/internal/widget/ListPopupWindow.java
+++ b/v7/appcompat/src/android/support/v7/internal/widget/ListPopupWindow.java
@@ -1310,14 +1310,13 @@
                     viewType = newType;
                 }
                 child = adapter.getView(i, child, this);
-                ;
 
                 // Compute child height spec
                 int heightMeasureSpec;
-                int childHeight = child.getLayoutParams().height;
-                if (childHeight > 0) {
-                    heightMeasureSpec = MeasureSpec
-                            .makeMeasureSpec(childHeight, MeasureSpec.EXACTLY);
+                final ViewGroup.LayoutParams childLp = child.getLayoutParams();
+                if (childLp != null && childLp.height > 0) {
+                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(childLp.height,
+                            MeasureSpec.EXACTLY);
                 } else {
                     heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
                 }
diff --git a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_disabled_holo_dark.png b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_disabled_holo_dark.png
index b47d666..458a2a6 100644
--- a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_disabled_holo_dark.png
+++ b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_disabled_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_off_holo_dark.png b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_off_holo_dark.png
index 13d803c..c91faa9 100644
--- a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_off_holo_dark.png
+++ b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_off_holo_light.png b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_off_holo_light.png
index 3ae436b..14c9183 100644
--- a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_off_holo_light.png
+++ b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_off_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_0_holo_dark.png b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_0_holo_dark.png
index 24824fc..b388d86 100644
--- a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_0_holo_dark.png
+++ b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_0_holo_light.png b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_0_holo_light.png
index af3819b..76c1323 100644
--- a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_0_holo_light.png
+++ b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_1_holo_dark.png b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_1_holo_dark.png
index 83dc251..fd39f9d 100644
--- a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_1_holo_dark.png
+++ b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_1_holo_light.png b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_1_holo_light.png
index 8d9d592..c74727a 100644
--- a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_1_holo_light.png
+++ b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_2_holo_dark.png b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_2_holo_dark.png
index 1310ec9..826c9ae 100644
--- a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_2_holo_dark.png
+++ b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_2_holo_light.png b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_2_holo_light.png
index 1705074..d0baec3 100644
--- a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_2_holo_light.png
+++ b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_holo_dark.png b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_holo_dark.png
index 7027b88..c60ff59 100644
--- a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_holo_dark.png
+++ b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_holo_light.png b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_holo_light.png
index 7027b88..75552cc 100644
--- a/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_holo_light.png
+++ b/v7/mediarouter/res/drawable-hdpi/mr_ic_media_route_on_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_off_holo_dark.png b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_off_holo_dark.png
index 6764598..9d92648 100644
--- a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_off_holo_dark.png
+++ b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_off_holo_light.png b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_off_holo_light.png
index 94e0bb6..3e27fc8 100644
--- a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_off_holo_light.png
+++ b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_off_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_0_holo_dark.png b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_0_holo_dark.png
index 5ce2f20..72b9e78 100644
--- a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_0_holo_dark.png
+++ b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_0_holo_light.png b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_0_holo_light.png
index 5105e90..bd462a2 100644
--- a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_0_holo_light.png
+++ b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_1_holo_dark.png b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_1_holo_dark.png
index 68c06ed..0a2cc89 100644
--- a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_1_holo_dark.png
+++ b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_1_holo_light.png b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_1_holo_light.png
index 6e9b144..d162503 100644
--- a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_1_holo_light.png
+++ b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_2_holo_dark.png b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_2_holo_dark.png
index 45dc56f..997e32b 100644
--- a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_2_holo_dark.png
+++ b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_2_holo_light.png b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_2_holo_light.png
index 46e743a..d314967 100644
--- a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_2_holo_light.png
+++ b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_holo_dark.png b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_holo_dark.png
index e384691..f15d7a9d 100644
--- a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_holo_dark.png
+++ b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_holo_light.png b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_holo_light.png
index e384691..26d46f8 100644
--- a/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_holo_light.png
+++ b/v7/mediarouter/res/drawable-mdpi/mr_ic_media_route_on_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_disabled_holo_dark.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_disabled_holo_dark.png
index 1d48e12..045eee0 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_disabled_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_disabled_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_disabled_holo_light.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_disabled_holo_light.png
index 2c8d1ec..6e14e29 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_disabled_holo_light.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_disabled_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_off_holo_dark.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_off_holo_dark.png
index 00b2043..121bbf6 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_off_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_off_holo_light.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_off_holo_light.png
index ce1d939..468a0c3 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_off_holo_light.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_off_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_0_holo_dark.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_0_holo_dark.png
index 3064b46..414a322 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_0_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_0_holo_light.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_0_holo_light.png
index 4316686..6088a48 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_0_holo_light.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_1_holo_dark.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_1_holo_dark.png
index 25c4e31..363d7d4 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_1_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_1_holo_light.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_1_holo_light.png
index 8e32bd2..edf731e 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_1_holo_light.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_2_holo_dark.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_2_holo_dark.png
index aeaa78f..85cba7b 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_2_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_2_holo_light.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_2_holo_light.png
index 85277fa..e65ac31 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_2_holo_light.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_holo_dark.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_holo_dark.png
index b01dbe8..d8e3e3a 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_holo_light.png b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_holo_light.png
index c19a2ad..562dc9a 100644
--- a/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_holo_light.png
+++ b/v7/mediarouter/res/drawable-xhdpi/mr_ic_media_route_on_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_disabled_holo_dark.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_disabled_holo_dark.png
index 7b0c383..178774c 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_disabled_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_disabled_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_disabled_holo_light.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_disabled_holo_light.png
index efb624e..2dc2092 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_disabled_holo_light.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_disabled_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_off_holo_dark.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_off_holo_dark.png
index 5ee57e4..592ee8c 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_off_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_off_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_off_holo_light.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_off_holo_light.png
index 6bc2e4a..f0549e2 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_off_holo_light.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_off_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_0_holo_dark.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_0_holo_dark.png
index c13af9c..91268f5 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_0_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_0_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_0_holo_light.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_0_holo_light.png
index 744fb42..9d5436f 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_0_holo_light.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_0_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_1_holo_dark.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_1_holo_dark.png
index ca4d59c..8e77483 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_1_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_1_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_1_holo_light.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_1_holo_light.png
index fde5688..f396d22 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_1_holo_light.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_1_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_2_holo_dark.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_2_holo_dark.png
index b8715c3..260bab4 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_2_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_2_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_2_holo_light.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_2_holo_light.png
index 668bb25..2c9fb1d 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_2_holo_light.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_2_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_holo_dark.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_holo_dark.png
index 7f54a62..bdbd59c 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_holo_dark.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_holo_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_holo_light.png b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_holo_light.png
index 2df924d..f5c33dd 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_holo_light.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/mr_ic_media_route_on_holo_light.png
Binary files differ
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
index f30e7bb..c3d34ec 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteButton.java
@@ -506,11 +506,6 @@
         }
     }
 
-    static interface AttachCallback {
-        void onAttachedToWindow();
-        void onDetachedFromWindow();
-    }
-
     private final class MediaRouterCallback extends MediaRouter.Callback {
         @Override
         public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) {
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java
index 91a4c08..25e7ff8 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteChooserDialog.java
@@ -100,7 +100,7 @@
     /**
      * Returns true if the route should be included in the list.
      * <p>
-     * The default implementation returns true for non-default routes that
+     * The default implementation returns true for enabled non-default routes that
      * match the selector.  Subclasses can override this method to filter routes
      * differently.
      * </p>
@@ -109,7 +109,7 @@
      * @return True if the route should be included in the chooser dialog.
      */
     public boolean onFilterRoute(MediaRouter.RouteInfo route) {
-        return !route.isDefault() && route.matchesSelector(mSelector);
+        return !route.isDefault() && route.isEnabled() && route.matchesSelector(mSelector);
     }
 
     @Override
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
index ec31253..3fe9c78 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
@@ -251,8 +251,8 @@
         if (icon != mCurrentIconDrawable) {
             mCurrentIconDrawable = icon;
 
-            // There seems to be a bug in the framework where feature drawables
-            // will not start animating unless they experience a transition from
+            // Prior to KLP MR1 there was a bug in ImageView that caused feature drawables
+            // to not start animating unless they experienced a transition from
             // invisible to visible.  So we force the drawable to be invisible here.
             // The window will make the drawable visible when attached.
             icon.setVisible(false, true);
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaControlIntent.java b/v7/mediarouter/src/android/support/v7/media/MediaControlIntent.java
index d4d96f3..638701f5 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaControlIntent.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaControlIntent.java
@@ -105,7 +105,8 @@
  *
  * <h3>Remote playback routes</h3>
  * <p>
- * Remote playback routes present media remotely by playing content from a Uri.
+ * {@link #CATEGORY_REMOTE_PLAYBACK Remote playback} routes present media remotely
+ * by playing content from a Uri.
  * These routes destinations take responsibility for fetching and rendering content
  * on their own.  Applications do not render the content themselves; instead, applications
  * send control requests to initiate play, pause, resume, or stop media items and receive
@@ -267,6 +268,8 @@
  * </p>
  */
 public final class MediaControlIntent {
+    /* Route categories. */
+
     /**
      * Media control category: Live audio.
      * <p>
@@ -276,6 +279,8 @@
      * </p><p>
      * When a live audio route is selected, audio routing is transparent to the application.
      * All audio played on the media stream will be routed to the selected destination.
+     * </p><p>
+     * Refer to the class documentation for details about live audio routes.
      * </p>
      */
     public static final String CATEGORY_LIVE_AUDIO = "android.media.intent.category.LIVE_AUDIO";
@@ -293,6 +298,8 @@
      * destination.  For certain live video routes, the application may also use a
      * {@link android.app.Presentation Presentation} to replace the mirrored view
      * on the external display with different content.
+     * </p><p>
+     * Refer to the class documentation for details about live video routes.
      * </p>
      *
      * @see MediaRouter.RouteInfo#getPresentationDisplay()
@@ -311,6 +318,8 @@
      * playing on the destination by sending media control actions to the route.
      * The application may also receive status updates from the route regarding
      * remote playback.
+     * </p><p>
+     * Refer to the class documentation for details about remote playback routes.
      * </p>
      *
      * @see MediaRouter.RouteInfo#sendControlRequest
@@ -871,6 +880,8 @@
      */
     public static final String ACTION_END_SESSION = "android.media.intent.action.END_SESSION";
 
+    /* Extras and related constants. */
+
     /**
      * Bundle extra: Media session id.
      * <p>
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouteProvider.java b/v7/mediarouter/src/android/support/v7/media/MediaRouteProvider.java
index aec7b2b..54596b1 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaRouteProvider.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouteProvider.java
@@ -16,12 +16,12 @@
 
 package android.support.v7.media;
 
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Handler;
 import android.os.Message;
 import android.support.v7.media.MediaRouter.ControlRequestCallback;
-import android.text.TextUtils;
 
 /**
  * Media route providers are used to publish additional media routes for
@@ -84,7 +84,7 @@
 
         mContext = context;
         if (metadata == null) {
-            mMetadata = new ProviderMetadata(context.getPackageName());
+            mMetadata = new ProviderMetadata(new ComponentName(context, getClass()));
         } else {
             mMetadata = metadata;
         }
@@ -256,30 +256,33 @@
      * </p>
      */
     public static final class ProviderMetadata {
-        private final String mPackageName;
+        private final ComponentName mComponentName;
 
-        /**
-         * Creates a provider metadata object.
-         *
-         * @param packageName The provider application's package name.
-         */
-        public ProviderMetadata(String packageName) {
-            if (TextUtils.isEmpty(packageName)) {
-                throw new IllegalArgumentException("packageName must not be null or empty");
+        ProviderMetadata(ComponentName componentName) {
+            if (componentName == null) {
+                throw new IllegalArgumentException("componentName must not be null");
             }
-            mPackageName = packageName;
+            mComponentName = componentName;
         }
 
         /**
-         * Gets the provider application's package name.
+         * Gets the provider's package name.
          */
         public String getPackageName() {
-            return mPackageName;
+            return mComponentName.getPackageName();
+        }
+
+        /**
+         * Gets the provider's component name.
+         */
+        public ComponentName getComponentName() {
+            return mComponentName;
         }
 
         @Override
         public String toString() {
-            return "ProviderMetadata{ packageName=" + mPackageName + " }";
+            return "ProviderMetadata{ componentName="
+                    + mComponentName.flattenToShortString() + " }";
         }
     }
 
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouteProviderProtocol.java b/v7/mediarouter/src/android/support/v7/media/MediaRouteProviderProtocol.java
new file mode 100644
index 0000000..f44dcac
--- /dev/null
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouteProviderProtocol.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2013 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.support.v7.media;
+
+import android.content.Intent;
+import android.os.Messenger;
+
+/**
+ * Defines the communication protocol for media route provider services.
+ * @hide
+ */
+abstract class MediaRouteProviderProtocol {
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     * Put this in your manifest.
+     */
+    public static final String SERVICE_INTERFACE =
+            "android.media.MediaRouteProviderService";
+
+    /*
+     * Messages sent from the client to the service.
+     * DO NOT RENUMBER THESE!
+     */
+
+    /** (client v1)
+     * Register client.
+     * - replyTo : client messenger
+     * - arg1    : request id
+     * - arg2    : client version
+     */
+    public static final int CLIENT_MSG_REGISTER = 1;
+
+    /** (client v1)
+     * Unregister client.
+     * - replyTo : client messenger
+     * - arg1    : request id
+     */
+    public static final int CLIENT_MSG_UNREGISTER = 2;
+
+    /** (client v1)
+     * Create route controller.
+     * - replyTo : client messenger
+     * - arg1    : request id
+     * - arg2    : route controller id
+     * - CLIENT_DATA_ROUTE_ID : route id string
+     */
+    public static final int CLIENT_MSG_CREATE_ROUTE_CONTROLLER = 3;
+
+    /** (client v1)
+     * Release route controller.
+     * - replyTo : client messenger
+     * - arg1    : request id
+     * - arg2    : route controller id
+     */
+    public static final int CLIENT_MSG_RELEASE_ROUTE_CONTROLLER = 4;
+
+    /** (client v1)
+     * Select route.
+     * - replyTo : client messenger
+     * - arg1    : request id
+     * - arg2    : route controller id
+     */
+    public static final int CLIENT_MSG_SELECT_ROUTE = 5;
+
+    /** (client v1)
+     * Unselect route.
+     * - replyTo : client messenger
+     * - arg1    : request id
+     * - arg2    : route controller id
+     */
+    public static final int CLIENT_MSG_UNSELECT_ROUTE = 6;
+
+    /** (client v1)
+     * Set route volume.
+     * - replyTo : client messenger
+     * - arg1    : request id
+     * - arg2    : route controller id
+     * - CLIENT_DATA_VOLUME : volume integer
+     */
+    public static final int CLIENT_MSG_SET_ROUTE_VOLUME = 7;
+
+    /** (client v1)
+     * Update route volume.
+     * - replyTo : client messenger
+     * - arg1    : request id
+     * - arg2    : route controller id
+     * - CLIENT_DATA_VOLUME : volume delta integer
+     */
+    public static final int CLIENT_MSG_UPDATE_ROUTE_VOLUME = 8;
+
+    /** (client v1)
+     * Route control request.
+     * - replyTo : client messenger
+     * - arg1    : request id
+     * - arg2    : route controller id
+     * - obj     : media control intent
+     */
+    public static final int CLIENT_MSG_ROUTE_CONTROL_REQUEST = 9;
+
+    /** (client v1)
+     * Sets the discovery request.
+     * - replyTo : client messenger
+     * - arg1    : request id
+     * - obj     : discovery request bundle, or null if none
+     */
+    public static final int CLIENT_MSG_SET_DISCOVERY_REQUEST = 10;
+
+    public static final String CLIENT_DATA_ROUTE_ID = "routeId";
+    public static final String CLIENT_DATA_VOLUME = "volume";
+
+    /*
+     * Messages sent from the service to the client.
+     * DO NOT RENUMBER THESE!
+     */
+
+    /** (service v1)
+     * Generic failure sent in response to any unrecognized or malformed request.
+     * - arg1    : request id
+     */
+    public static final int SERVICE_MSG_GENERIC_FAILURE = 0;
+
+    /** (service v1)
+     * Generic failure sent in response to a successful message.
+     * - arg1    : request id
+     */
+    public static final int SERVICE_MSG_GENERIC_SUCCESS = 1;
+
+    /** (service v1)
+     * Registration succeeded.
+     * - arg1    : request id
+     * - arg2    : server version
+     * - obj     : route provider descriptor bundle, or null
+     */
+    public static final int SERVICE_MSG_REGISTERED = 2;
+
+    /** (service v1)
+     * Route control request success result.
+     * - arg1    : request id
+     * - obj     : result data bundle, or null
+     */
+    public static final int SERVICE_MSG_CONTROL_REQUEST_SUCCEEDED = 3;
+
+    /** (service v1)
+     * Route control request failure result.
+     * - arg1    : request id
+     * - obj     : result data bundle, or null
+     * - SERVICE_DATA_ERROR: error message
+     */
+    public static final int SERVICE_MSG_CONTROL_REQUEST_FAILED = 4;
+
+    /** (service v1)
+     * Route provider descriptor changed.  (unsolicited event)
+     * - arg1    : reserved (0)
+     * - obj     : route provider descriptor bundle, or null
+     */
+    public static final int SERVICE_MSG_DESCRIPTOR_CHANGED = 5;
+
+    public static final String SERVICE_DATA_ERROR = "error";
+
+    /*
+     * Recognized client version numbers.  (Reserved for future use.)
+     * DO NOT RENUMBER THESE!
+     */
+
+    public static final int CLIENT_VERSION_1 = 1;
+    public static final int CLIENT_VERSION_CURRENT = CLIENT_VERSION_1;
+
+    /*
+     * Recognized server version numbers.  (Reserved for future use.)
+     * DO NOT RENUMBER THESE!
+     */
+
+    public static final int SERVICE_VERSION_1 = 1;
+    public static final int SERVICE_VERSION_CURRENT = SERVICE_VERSION_1;
+
+    /**
+     * Returns true if the messenger object is valid.
+     * <p>
+     * The messenger constructor and unparceling code does not check whether the
+     * provided IBinder is a valid IMessenger object.  As a result, it's possible
+     * for a peer to send an invalid IBinder that will result in crashes downstream.
+     * This method checks that the messenger is in a valid state.
+     * </p>
+     */
+    public static boolean isValidRemoteMessenger(Messenger messenger) {
+        try {
+            return messenger != null && messenger.getBinder() != null;
+        } catch (NullPointerException ex) {
+            // If the messenger was constructed with a binder interface other than
+            // IMessenger then the call to getBinder() will crash with an NPE.
+            return false;
+        }
+    }
+}
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouteProviderService.java b/v7/mediarouter/src/android/support/v7/media/MediaRouteProviderService.java
index de34c8e..d3f548d 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaRouteProviderService.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouteProviderService.java
@@ -32,6 +32,8 @@
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 
+import static android.support.v7.media.MediaRouteProviderProtocol.*;
+
 /**
  * Base class for media route provider services.
  * <p>
@@ -68,164 +70,7 @@
      * The {@link Intent} that must be declared as handled by the service.
      * Put this in your manifest.
      */
-    public static final String SERVICE_INTERFACE =
-            "android.media.MediaRouteProviderService";
-
-    /*
-     * Messages sent from the client to the service.
-     * DO NOT RENUMBER THESE!
-     */
-
-    /** (client v1)
-     * Register client.
-     * - replyTo : client messenger
-     * - arg1    : request id
-     * - arg2    : client version
-     */
-    static final int CLIENT_MSG_REGISTER = 1;
-
-    /** (client v1)
-     * Unregister client.
-     * - replyTo : client messenger
-     * - arg1    : request id
-     */
-    static final int CLIENT_MSG_UNREGISTER = 2;
-
-    /** (client v1)
-     * Create route controller.
-     * - replyTo : client messenger
-     * - arg1    : request id
-     * - arg2    : route controller id
-     * - CLIENT_DATA_ROUTE_ID : route id string
-     */
-    static final int CLIENT_MSG_CREATE_ROUTE_CONTROLLER = 3;
-
-    /** (client v1)
-     * Release route controller.
-     * - replyTo : client messenger
-     * - arg1    : request id
-     * - arg2    : route controller id
-     */
-    static final int CLIENT_MSG_RELEASE_ROUTE_CONTROLLER = 4;
-
-    /** (client v1)
-     * Select route.
-     * - replyTo : client messenger
-     * - arg1    : request id
-     * - arg2    : route controller id
-     */
-    static final int CLIENT_MSG_SELECT_ROUTE = 5;
-
-    /** (client v1)
-     * Unselect route.
-     * - replyTo : client messenger
-     * - arg1    : request id
-     * - arg2    : route controller id
-     */
-    static final int CLIENT_MSG_UNSELECT_ROUTE = 6;
-
-    /** (client v1)
-     * Set route volume.
-     * - replyTo : client messenger
-     * - arg1    : request id
-     * - arg2    : route controller id
-     * - CLIENT_DATA_VOLUME : volume integer
-     */
-    static final int CLIENT_MSG_SET_ROUTE_VOLUME = 7;
-
-    /** (client v1)
-     * Update route volume.
-     * - replyTo : client messenger
-     * - arg1    : request id
-     * - arg2    : route controller id
-     * - CLIENT_DATA_VOLUME : volume delta integer
-     */
-    static final int CLIENT_MSG_UPDATE_ROUTE_VOLUME = 8;
-
-    /** (client v1)
-     * Route control request.
-     * - replyTo : client messenger
-     * - arg1    : request id
-     * - arg2    : route controller id
-     * - obj     : media control intent
-     */
-    static final int CLIENT_MSG_ROUTE_CONTROL_REQUEST = 9;
-
-    /** (client v1)
-     * Sets the discovery request.
-     * - replyTo : client messenger
-     * - arg1    : request id
-     * - obj     : discovery request bundle, or null if none
-     */
-    static final int CLIENT_MSG_SET_DISCOVERY_REQUEST = 10;
-
-    static final String CLIENT_DATA_ROUTE_ID = "routeId";
-    static final String CLIENT_DATA_VOLUME = "volume";
-
-    /*
-     * Messages sent from the service to the client.
-     * DO NOT RENUMBER THESE!
-     */
-
-    /** (service v1)
-     * Generic failure sent in response to any unrecognized or malformed request.
-     * - arg1    : request id
-     */
-    static final int SERVICE_MSG_GENERIC_FAILURE = 0;
-
-    /** (service v1)
-     * Generic failure sent in response to a successful message.
-     * - arg1    : request id
-     */
-    static final int SERVICE_MSG_GENERIC_SUCCESS = 1;
-
-    /** (service v1)
-     * Registration succeeded.
-     * - arg1    : request id
-     * - arg2    : server version
-     * - obj     : route provider descriptor bundle, or null
-     */
-    static final int SERVICE_MSG_REGISTERED = 2;
-
-    /** (service v1)
-     * Route control request success result.
-     * - arg1    : request id
-     * - obj     : result data bundle, or null
-     */
-    static final int SERVICE_MSG_CONTROL_REQUEST_SUCCEEDED = 3;
-
-    /** (service v1)
-     * Route control request failure result.
-     * - arg1    : request id
-     * - obj     : result data bundle, or null
-     * - SERVICE_DATA_ERROR: error message
-     */
-    static final int SERVICE_MSG_CONTROL_REQUEST_FAILED = 4;
-
-    /** (service v1)
-     * Route provider descriptor changed.  (unsolicited event)
-     * - arg1    : reserved (0)
-     * - obj     : route provider descriptor bundle, or null
-     */
-    static final int SERVICE_MSG_DESCRIPTOR_CHANGED = 5;
-
-    static final String SERVICE_DATA_ERROR = "error";
-
-    /*
-     * Recognized client version numbers.  (Reserved for future use.)
-     * DO NOT RENUMBER THESE!
-     */
-
-    static final int CLIENT_VERSION_1 = 1;
-    static final int CLIENT_VERSION_CURRENT = CLIENT_VERSION_1;
-
-    /*
-     * Recognized server version numbers.  (Reserved for future use.)
-     * DO NOT RENUMBER THESE!
-     */
-
-    static final int SERVICE_VERSION_1 = 1;
-    static final int SERVICE_VERSION_CURRENT = SERVICE_VERSION_1;
+    public static final String SERVICE_INTERFACE = MediaRouteProviderProtocol.SERVICE_INTERFACE;
 
     /*
      * Private messages used internally.  (Yes, you can renumber these.)
@@ -614,25 +459,6 @@
         return "Client connection " + messenger.getBinder().toString();
     }
 
-    /**
-     * Returns true if the messenger object is valid.
-     * <p>
-     * The messenger constructor and unparceling code does not check whether the
-     * provided IBinder is a valid IMessenger object.  As a result, it's possible
-     * for a peer to send an invalid IBinder that will result in crashes downstream.
-     * This method checks that the messenger is in a valid state.
-     * </p>
-     */
-    static boolean isValidRemoteMessenger(Messenger messenger) {
-        try {
-            return messenger != null && messenger.getBinder() != null;
-        } catch (NullPointerException ex) {
-            // If the messenger was constructed with a binder interface other than
-            // IMessenger then the call to getBinder() will crash with an NPE.
-            return false;
-        }
-    }
-
     private final class PrivateHandler extends Handler {
         @Override
         public void handleMessage(Message msg) {
diff --git a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
index 247267d..7b83cc0 100644
--- a/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
+++ b/v7/mediarouter/src/android/support/v7/media/MediaRouter.java
@@ -16,6 +16,7 @@
 
 package android.support.v7.media;
 
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -96,7 +97,7 @@
      * Flag for {@link #addCallback}: Do not filter route events.
      * <p>
      * When this flag is specified, the callback will be invoked for events that affect any
-     * route event if they do not match the callback's associated media route selector.
+     * route even if they do not match the callback's filter.
      * </p>
      */
     public static final int CALLBACK_FLAG_UNFILTERED_EVENTS = 1 << 1;
@@ -1152,13 +1153,20 @@
         }
 
         /**
-         * Gets the package name of the media route provider service.
+         * Gets the package name of the media route provider.
          */
         public String getPackageName() {
             return mMetadata.getPackageName();
         }
 
         /**
+         * Gets the component name of the media route provider.
+         */
+        public ComponentName getComponentName() {
+            return mMetadata.getComponentName();
+        }
+
+        /**
          * Gets the {@link MediaRouter.RouteInfo routes} published by this route provider.
          */
         public List<RouteInfo> getRoutes() {
@@ -1368,9 +1376,10 @@
      * state and the bulk of the media router implementation lives here.
      * </p>
      */
-    private static final class GlobalMediaRouter implements SystemMediaRouteProvider.SyncCallback {
+    private static final class GlobalMediaRouter
+            implements SystemMediaRouteProvider.SyncCallback,
+            RegisteredMediaRouteProviderWatcher.Callback {
         private final Context mApplicationContext;
-        private final MediaRouter mApplicationRouter;
         private final ArrayList<WeakReference<MediaRouter>> mRouters =
                 new ArrayList<WeakReference<MediaRouter>>();
         private final ArrayList<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
@@ -1394,7 +1403,6 @@
         GlobalMediaRouter(Context applicationContext) {
             mApplicationContext = applicationContext;
             mDisplayManager = DisplayManagerCompat.getInstance(applicationContext);
-            mApplicationRouter = getRouter(applicationContext);
 
             // Add the system media route provider for interoperating with
             // the framework media router.  This one is special and receives
@@ -1407,7 +1415,7 @@
             // Start watching for routes published by registered media route
             // provider services.
             mRegisteredProviderWatcher = new RegisteredMediaRouteProviderWatcher(
-                    mApplicationContext, mApplicationRouter);
+                    mApplicationContext, this);
             mRegisteredProviderWatcher.start();
         }
 
@@ -1584,6 +1592,7 @@
             }
         }
 
+        @Override
         public void addProvider(MediaRouteProvider providerInstance) {
             int index = findProviderInfo(providerInstance);
             if (index < 0) {
@@ -1603,6 +1612,7 @@
             }
         }
 
+        @Override
         public void removeProvider(MediaRouteProvider providerInstance) {
             int index = findProviderInfo(providerInstance);
             if (index >= 0) {
@@ -1753,7 +1763,8 @@
             // Although route descriptor ids are unique within a provider, it's
             // possible for there to be two providers with the same package name.
             // Therefore we must dedupe the composite id.
-            String uniqueId = provider.getPackageName() + ":" + routeDescriptorId;
+            String uniqueId = provider.getComponentName().flattenToShortString()
+                    + ":" + routeDescriptorId;
             if (findRouteByUniqueId(uniqueId) < 0) {
                 return uniqueId;
             }
diff --git a/v7/mediarouter/src/android/support/v7/media/RegisteredMediaRouteProvider.java b/v7/mediarouter/src/android/support/v7/media/RegisteredMediaRouteProvider.java
index b179b85..641e80d 100644
--- a/v7/mediarouter/src/android/support/v7/media/RegisteredMediaRouteProvider.java
+++ b/v7/mediarouter/src/android/support/v7/media/RegisteredMediaRouteProvider.java
@@ -36,6 +36,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static android.support.v7.media.MediaRouteProviderProtocol.*;
+
 /**
  * Maintains a connection to a particular media route provider service.
  */
@@ -54,7 +56,7 @@
     private boolean mConnectionReady;
 
     public RegisteredMediaRouteProvider(Context context, ComponentName componentName) {
-        super(context, new ProviderMetadata(componentName.getPackageName()));
+        super(context, new ProviderMetadata(componentName));
 
         mComponentName = componentName;
         mPrivateHandler = new PrivateHandler();
@@ -154,7 +156,7 @@
                 Log.d(TAG, this + ": Binding");
             }
 
-            Intent service = new Intent(MediaRouteProviderService.SERVICE_INTERFACE);
+            Intent service = new Intent(MediaRouteProviderProtocol.SERVICE_INTERFACE);
             service.setComponent(mComponentName);
             try {
                 mBound = getContext().bindService(service, this, Context.BIND_AUTO_CREATE);
@@ -191,7 +193,7 @@
             disconnect();
 
             Messenger messenger = (service != null ? new Messenger(service) : null);
-            if (MediaRouteProviderService.isValidRemoteMessenger(messenger)) {
+            if (isValidRemoteMessenger(messenger)) {
                 Connection connection = new Connection(messenger);
                 if (connection.register()) {
                     mActiveConnection = connection;
@@ -397,9 +399,9 @@
 
         public boolean register() {
             mPendingRegisterRequestId = mNextRequestId++;
-            if (!sendRequest(MediaRouteProviderService.CLIENT_MSG_REGISTER,
+            if (!sendRequest(CLIENT_MSG_REGISTER,
                     mPendingRegisterRequestId,
-                    MediaRouteProviderService.CLIENT_VERSION_CURRENT, null, null)) {
+                    CLIENT_VERSION_CURRENT, null, null)) {
                 return false;
             }
 
@@ -413,7 +415,7 @@
         }
 
         public void dispose() {
-            sendRequest(MediaRouteProviderService.CLIENT_MSG_UNREGISTER, 0, 0, null, null);
+            sendRequest(CLIENT_MSG_UNREGISTER, 0, 0, null, null);
             mReceiveHandler.dispose();
             mServiceMessenger.getBinder().unlinkToDeath(this, 0);
 
@@ -454,7 +456,7 @@
                 Bundle descriptorBundle) {
             if (mServiceVersion == 0
                     && requestId == mPendingRegisterRequestId
-                    && serviceVersion >= MediaRouteProviderService.SERVICE_VERSION_1) {
+                    && serviceVersion >= SERVICE_VERSION_1) {
                 mPendingRegisterRequestId = 0;
                 mServiceVersion = serviceVersion;
                 onConnectionDescriptorChanged(this,
@@ -507,45 +509,45 @@
         public int createRouteController(String routeId) {
             int controllerId = mNextControllerId++;
             Bundle data = new Bundle();
-            data.putString(MediaRouteProviderService.CLIENT_DATA_ROUTE_ID, routeId);
-            sendRequest(MediaRouteProviderService.CLIENT_MSG_CREATE_ROUTE_CONTROLLER,
+            data.putString(CLIENT_DATA_ROUTE_ID, routeId);
+            sendRequest(CLIENT_MSG_CREATE_ROUTE_CONTROLLER,
                     mNextRequestId++, controllerId, null, data);
             return controllerId;
         }
 
         public void releaseRouteController(int controllerId) {
-            sendRequest(MediaRouteProviderService.CLIENT_MSG_RELEASE_ROUTE_CONTROLLER,
+            sendRequest(CLIENT_MSG_RELEASE_ROUTE_CONTROLLER,
                     mNextRequestId++, controllerId, null, null);
         }
 
         public void selectRoute(int controllerId) {
-            sendRequest(MediaRouteProviderService.CLIENT_MSG_SELECT_ROUTE,
+            sendRequest(CLIENT_MSG_SELECT_ROUTE,
                     mNextRequestId++, controllerId, null, null);
         }
 
         public void unselectRoute(int controllerId) {
-            sendRequest(MediaRouteProviderService.CLIENT_MSG_UNSELECT_ROUTE,
+            sendRequest(CLIENT_MSG_UNSELECT_ROUTE,
                     mNextRequestId++, controllerId, null, null);
         }
 
         public void setVolume(int controllerId, int volume) {
             Bundle data = new Bundle();
-            data.putInt(MediaRouteProviderService.CLIENT_DATA_VOLUME, volume);
-            sendRequest(MediaRouteProviderService.CLIENT_MSG_SET_ROUTE_VOLUME,
+            data.putInt(CLIENT_DATA_VOLUME, volume);
+            sendRequest(CLIENT_MSG_SET_ROUTE_VOLUME,
                     mNextRequestId++, controllerId, null, data);
         }
 
         public void updateVolume(int controllerId, int delta) {
             Bundle data = new Bundle();
-            data.putInt(MediaRouteProviderService.CLIENT_DATA_VOLUME, delta);
-            sendRequest(MediaRouteProviderService.CLIENT_MSG_UPDATE_ROUTE_VOLUME,
+            data.putInt(CLIENT_DATA_VOLUME, delta);
+            sendRequest(CLIENT_MSG_UPDATE_ROUTE_VOLUME,
                     mNextRequestId++, controllerId, null, data);
         }
 
         public boolean sendControlRequest(int controllerId, Intent intent,
                 ControlRequestCallback callback) {
             int requestId = mNextRequestId++;
-            if (sendRequest(MediaRouteProviderService.CLIENT_MSG_ROUTE_CONTROL_REQUEST,
+            if (sendRequest(CLIENT_MSG_ROUTE_CONTROL_REQUEST,
                     requestId, controllerId, intent, null)) {
                 if (callback != null) {
                     mPendingCallbacks.put(requestId, callback);
@@ -556,7 +558,7 @@
         }
 
         public void setDiscoveryRequest(MediaRouteDiscoveryRequest request) {
-            sendRequest(MediaRouteProviderService.CLIENT_MSG_SET_DISCOVERY_REQUEST,
+            sendRequest(CLIENT_MSG_SET_DISCOVERY_REQUEST,
                     mNextRequestId++, 0, request != null ? request.asBundle() : null, null);
         }
 
@@ -574,7 +576,7 @@
             } catch (DeadObjectException ex) {
                 // The service died.
             } catch (RemoteException ex) {
-                if (what != MediaRouteProviderService.CLIENT_MSG_UNREGISTER) {
+                if (what != CLIENT_MSG_UNREGISTER) {
                     Log.e(TAG, "Could not send message to service.", ex);
                 }
             }
@@ -627,37 +629,37 @@
         private boolean processMessage(Connection connection,
                 int what, int requestId, int arg, Object obj, Bundle data) {
             switch (what) {
-                case MediaRouteProviderService.SERVICE_MSG_GENERIC_FAILURE:
+                case SERVICE_MSG_GENERIC_FAILURE:
                     connection.onGenericFailure(requestId);
                     return true;
 
-                case MediaRouteProviderService.SERVICE_MSG_GENERIC_SUCCESS:
+                case SERVICE_MSG_GENERIC_SUCCESS:
                     connection.onGenericSuccess(requestId);
                     return true;
 
-                case MediaRouteProviderService.SERVICE_MSG_REGISTERED:
+                case SERVICE_MSG_REGISTERED:
                     if (obj == null || obj instanceof Bundle) {
                         return connection.onRegistered(requestId, arg, (Bundle)obj);
                     }
                     break;
 
-                case MediaRouteProviderService.SERVICE_MSG_DESCRIPTOR_CHANGED:
+                case SERVICE_MSG_DESCRIPTOR_CHANGED:
                     if (obj == null || obj instanceof Bundle) {
                         return connection.onDescriptorChanged((Bundle)obj);
                     }
                     break;
 
-                case MediaRouteProviderService.SERVICE_MSG_CONTROL_REQUEST_SUCCEEDED:
+                case SERVICE_MSG_CONTROL_REQUEST_SUCCEEDED:
                     if (obj == null || obj instanceof Bundle) {
                         return connection.onControlRequestSucceeded(
                                 requestId, (Bundle)obj);
                     }
                     break;
 
-                case MediaRouteProviderService.SERVICE_MSG_CONTROL_REQUEST_FAILED:
+                case SERVICE_MSG_CONTROL_REQUEST_FAILED:
                     if (obj == null || obj instanceof Bundle) {
                         String error = (data == null ? null :
-                                data.getString(MediaRouteProviderService.SERVICE_DATA_ERROR));
+                                data.getString(SERVICE_DATA_ERROR));
                         return connection.onControlRequestFailed(
                                 requestId, error, (Bundle)obj);
                     }
diff --git a/v7/mediarouter/src/android/support/v7/media/RegisteredMediaRouteProviderWatcher.java b/v7/mediarouter/src/android/support/v7/media/RegisteredMediaRouteProviderWatcher.java
index 6476459..2fb01d2 100644
--- a/v7/mediarouter/src/android/support/v7/media/RegisteredMediaRouteProviderWatcher.java
+++ b/v7/mediarouter/src/android/support/v7/media/RegisteredMediaRouteProviderWatcher.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.os.Handler;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -36,33 +37,59 @@
  */
 final class RegisteredMediaRouteProviderWatcher {
     private final Context mContext;
-    private final MediaRouter mRouter;
-    private final ArrayList<RegisteredMediaRouteProvider> mProviders =
-            new ArrayList<RegisteredMediaRouteProvider>();
+    private final Callback mCallback;
+    private final Handler mHandler;
     private final PackageManager mPackageManager;
 
-    public RegisteredMediaRouteProviderWatcher(Context context, MediaRouter router) {
+    private final ArrayList<RegisteredMediaRouteProvider> mProviders =
+            new ArrayList<RegisteredMediaRouteProvider>();
+    private boolean mRunning;
+
+    public RegisteredMediaRouteProviderWatcher(Context context, Callback callback) {
         mContext = context;
-        mRouter = router;
+        mCallback = callback;
+        mHandler = new Handler();
         mPackageManager = context.getPackageManager();
     }
 
     public void start() {
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_PACKAGE_ADDED);
-        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
-        mContext.registerReceiver(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                scanPackages();
-            }
-        }, filter);
+        if (!mRunning) {
+            mRunning = true;
 
-        scanPackages();
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+            filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+            filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+            filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+            filter.addDataScheme("package");
+            mContext.registerReceiver(mScanPackagesReceiver, filter, null, mHandler);
+
+            // Scan packages.
+            // Also has the side-effect of restarting providers if needed.
+            mHandler.post(mScanPackagesRunnable);
+        }
+    }
+
+    public void stop() {
+        if (mRunning) {
+            mRunning = false;
+
+            mContext.unregisterReceiver(mScanPackagesReceiver);
+            mHandler.removeCallbacks(mScanPackagesRunnable);
+
+            // Stop all providers.
+            for (int i = mProviders.size() - 1; i >= 0; i--) {
+                mProviders.get(i).stop();
+            }
+        }
     }
 
     private void scanPackages() {
+        if (!mRunning) {
+            return;
+        }
+
         // Add providers for all new services.
         // Reorder the list so that providers left at the end will be the ones to remove.
         int targetIndex = 0;
@@ -77,9 +104,10 @@
                             new ComponentName(serviceInfo.packageName, serviceInfo.name));
                     provider.start();
                     mProviders.add(targetIndex++, provider);
-                    mRouter.addProvider(provider);
+                    mCallback.addProvider(provider);
                 } else if (sourceIndex >= targetIndex) {
                     RegisteredMediaRouteProvider provider = mProviders.get(sourceIndex);
+                    provider.start(); // restart the provider if needed
                     provider.rebindIfDisconnected();
                     Collections.swap(mProviders, sourceIndex, targetIndex++);
                 }
@@ -90,7 +118,7 @@
         if (targetIndex < mProviders.size()) {
             for (int i = mProviders.size() - 1; i >= targetIndex; i--) {
                 RegisteredMediaRouteProvider provider = mProviders.get(i);
-                mRouter.removeProvider(provider);
+                mCallback.removeProvider(provider);
                 mProviders.remove(provider);
                 provider.stop();
             }
@@ -107,4 +135,23 @@
         }
         return -1;
     }
+
+    private final BroadcastReceiver mScanPackagesReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            scanPackages();
+        }
+    };
+
+    private final Runnable mScanPackagesRunnable = new Runnable() {
+        @Override
+        public void run() {
+            scanPackages();
+        }
+    };
+
+    public interface Callback {
+        void addProvider(MediaRouteProvider provider);
+        void removeProvider(MediaRouteProvider provider);
+    }
 }
diff --git a/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java b/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java
index 9acd789..6a09650 100644
--- a/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java
+++ b/v7/mediarouter/src/android/support/v7/media/SystemMediaRouteProvider.java
@@ -17,6 +17,7 @@
 package android.support.v7.media;
 
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -43,7 +44,8 @@
     public static final String DEFAULT_ROUTE_ID = "DEFAULT_ROUTE";
 
     protected SystemMediaRouteProvider(Context context) {
-        super(context, new ProviderMetadata(PACKAGE_NAME));
+        super(context, new ProviderMetadata(new ComponentName(PACKAGE_NAME,
+                SystemMediaRouteProvider.class.getName())));
     }
 
     public static SystemMediaRouteProvider obtain(Context context, SyncCallback syncCallback) {
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/AllocationThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/AllocationThunker.java
index 72bb023..f3eb0da 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/AllocationThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/AllocationThunker.java
@@ -57,11 +57,19 @@
     }
 
     public int getUsage() {
-        return mN.getUsage();
+        try {
+            return mN.getUsage();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public int getBytesSize() {
-        return mN.getBytesSize();
+        try {
+            return mN.getBytesSize();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     AllocationThunker(RenderScript rs, Type t, int usage, android.renderscript.Allocation na) {
@@ -73,15 +81,27 @@
     }
 
     public void syncAll(int srcLocation) {
-        mN.syncAll(srcLocation);
+        try {
+            mN.syncAll(srcLocation);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void ioSend() {
-        mN.ioSend();
+        try {
+            mN.ioSend();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void ioReceive() {
-        mN.ioReceive();
+        try {
+            mN.ioReceive();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void copyFrom(BaseObj[] d) {
@@ -92,126 +112,262 @@
         for (int i = 0; i < d.length; i++) {
             dN[i] = d[i].getNObj();
         }
-        mN.copyFrom(dN);
+        try {
+            mN.copyFrom(dN);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void copyFromUnchecked(int[] d) {
-        mN.copyFromUnchecked(d);
+        try {
+            mN.copyFromUnchecked(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyFromUnchecked(short[] d) {
-        mN.copyFromUnchecked(d);
+        try {
+            mN.copyFromUnchecked(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyFromUnchecked(byte[] d) {
-        mN.copyFromUnchecked(d);
+        try {
+            mN.copyFromUnchecked(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyFromUnchecked(float[] d) {
-        mN.copyFromUnchecked(d);
+        try {
+            mN.copyFromUnchecked(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void copyFrom(int[] d) {
-        mN.copyFrom(d);
+        try {
+            mN.copyFrom(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyFrom(short[] d) {
-        mN.copyFrom(d);
+        try {
+            mN.copyFrom(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyFrom(byte[] d) {
-        mN.copyFrom(d);
+        try {
+            mN.copyFrom(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyFrom(float[] d) {
-        mN.copyFrom(d);
+        try {
+            mN.copyFrom(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyFrom(Bitmap b) {
-        mN.copyFrom(b);
+        try {
+            mN.copyFrom(b);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyFrom(Allocation a) {
         AllocationThunker at = (AllocationThunker)a;
-        mN.copyFrom(at.mN);
+        try {
+            mN.copyFrom(at.mN);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
 
     public void setFromFieldPacker(int xoff, FieldPacker fp) {
-        android.renderscript.FieldPacker nfp =
-            new android.renderscript.FieldPacker(fp.getData());
-        mN.setFromFieldPacker(xoff, nfp);
+        try {
+            android.renderscript.FieldPacker nfp =
+                new android.renderscript.FieldPacker(fp.getData());
+            mN.setFromFieldPacker(xoff, nfp);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
-        android.renderscript.FieldPacker nfp =
-            new android.renderscript.FieldPacker(fp.getData());
-        mN.setFromFieldPacker(xoff, component_number, nfp);
+        try {
+            android.renderscript.FieldPacker nfp =
+                new android.renderscript.FieldPacker(fp.getData());
+            mN.setFromFieldPacker(xoff, component_number, nfp);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void generateMipmaps() {
-        mN.generateMipmaps();
+        try {
+            mN.generateMipmaps();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
-        mN.copy1DRangeFromUnchecked(off, count, d);
+        try {
+            mN.copy1DRangeFromUnchecked(off, count, d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
-        mN.copy1DRangeFromUnchecked(off, count, d);
+        try {
+            mN.copy1DRangeFromUnchecked(off, count, d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
-        mN.copy1DRangeFromUnchecked(off, count, d);
+        try {
+            mN.copy1DRangeFromUnchecked(off, count, d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
-        mN.copy1DRangeFromUnchecked(off, count, d);
+        try {
+            mN.copy1DRangeFromUnchecked(off, count, d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void copy1DRangeFrom(int off, int count, int[] d) {
-        mN.copy1DRangeFrom(off, count, d);
+        try {
+            mN.copy1DRangeFrom(off, count, d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copy1DRangeFrom(int off, int count, short[] d) {
-        mN.copy1DRangeFrom(off, count, d);
+        try {
+            mN.copy1DRangeFrom(off, count, d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copy1DRangeFrom(int off, int count, byte[] d) {
-        mN.copy1DRangeFrom(off, count, d);
+        try {
+            mN.copy1DRangeFrom(off, count, d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copy1DRangeFrom(int off, int count, float[] d) {
-        mN.copy1DRangeFrom(off, count, d);
+        try {
+            mN.copy1DRangeFrom(off, count, d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void copy1DRangeFrom(int off, int count, Allocation data, int dataOff) {
-        AllocationThunker at = (AllocationThunker)data;
-        mN.copy1DRangeFrom(off, count, at.mN, dataOff);
+        try {
+            AllocationThunker at = (AllocationThunker)data;
+            mN.copy1DRangeFrom(off, count, at.mN, dataOff);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
-        mN.copy2DRangeFrom(xoff, yoff, w, h, data);
+        try {
+            mN.copy2DRangeFrom(xoff, yoff, w, h, data);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
-        mN.copy2DRangeFrom(xoff, yoff, w, h, data);
+        try {
+            mN.copy2DRangeFrom(xoff, yoff, w, h, data);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
-        mN.copy2DRangeFrom(xoff, yoff, w, h, data);
+        try {
+            mN.copy2DRangeFrom(xoff, yoff, w, h, data);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
-        mN.copy2DRangeFrom(xoff, yoff, w, h, data);
+        try {
+            mN.copy2DRangeFrom(xoff, yoff, w, h, data);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void copy2DRangeFrom(int xoff, int yoff, int w, int h,
                                 Allocation data, int dataXoff, int dataYoff) {
-        AllocationThunker at = (AllocationThunker)data;
-        mN.copy2DRangeFrom(xoff, yoff, w, h, at.mN, dataXoff, dataYoff);
+        try {
+            AllocationThunker at = (AllocationThunker)data;
+            mN.copy2DRangeFrom(xoff, yoff, w, h, at.mN, dataXoff, dataYoff);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) {
-        mN.copy2DRangeFrom(xoff, yoff, data);
+        try {
+            mN.copy2DRangeFrom(xoff, yoff, data);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
 
     public void copyTo(Bitmap b) {
-        mN.copyTo(b);
+        try {
+            mN.copyTo(b);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyTo(byte[] d) {
-        mN.copyTo(d);
+        try {
+            mN.copyTo(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyTo(short[] d) {
-        mN.copyTo(d);
+        try {
+            mN.copyTo(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyTo(int[] d) {
-        mN.copyTo(d);
+        try {
+            mN.copyTo(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     public void copyTo(float[] d) {
-        mN.copyTo(d);
+        try {
+            mN.copyTo(d);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     // creation
@@ -225,11 +381,15 @@
         RenderScriptThunker rst = (RenderScriptThunker)rs;
         TypeThunker tt = (TypeThunker)type;
 
-        android.renderscript.Allocation a =
-            android.renderscript.Allocation.createTyped(rst.mN, tt.mN,
-                                                        convertMipmapControl(mips), usage);
-
-        return new AllocationThunker(rs, type, usage, a);
+        try {
+            android.renderscript.Allocation a =
+                android.renderscript.Allocation.createTyped(rst.mN, tt.mN,
+                                                            convertMipmapControl(mips),
+                                                            usage);
+            return new AllocationThunker(rs, type, usage, a);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     static public Allocation createFromBitmap(RenderScript rs, Bitmap b,
@@ -237,23 +397,32 @@
                                               int usage) {
 
         RenderScriptThunker rst = (RenderScriptThunker)rs;
-        android.renderscript.Allocation a =
-                android.renderscript.Allocation.createFromBitmap(
-                rst.mN, b, convertMipmapControl(mips), usage);
-        TypeThunker tt = new TypeThunker(rs, a.getType());
+        try {
+            android.renderscript.Allocation a =
+                android.renderscript.Allocation.createFromBitmap(rst.mN, b,
+                                                                 convertMipmapControl(mips),
+                                                                 usage);
+            TypeThunker tt = new TypeThunker(rs, a.getType());
+            return new AllocationThunker(rs, tt, usage, a);
 
-        return new AllocationThunker(rs, tt, usage, a);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b,
                                                      MipmapControl mips,
                                                      int usage) {
         RenderScriptThunker rst = (RenderScriptThunker)rs;
-        android.renderscript.Allocation a =
-                android.renderscript.Allocation.createCubemapFromBitmap(
-                rst.mN, b, convertMipmapControl(mips), usage);
-        TypeThunker tt = new TypeThunker(rs, a.getType());
-        return new AllocationThunker(rs, tt, usage, a);
+        try {
+            android.renderscript.Allocation a =
+                    android.renderscript.Allocation.createCubemapFromBitmap(
+                    rst.mN, b, convertMipmapControl(mips), usage);
+            TypeThunker tt = new TypeThunker(rs, a.getType());
+            return new AllocationThunker(rs, tt, usage, a);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     static public Allocation createCubemapFromCubeFaces(RenderScript rs,
@@ -266,12 +435,16 @@
                                                         MipmapControl mips,
                                                         int usage) {
         RenderScriptThunker rst = (RenderScriptThunker)rs;
-        android.renderscript.Allocation a =
-                android.renderscript.Allocation.createCubemapFromCubeFaces(
-                rst.mN, xpos, xneg, ypos, yneg, zpos, zneg,
-                convertMipmapControl(mips), usage);
-        TypeThunker tt = new TypeThunker(rs, a.getType());
-        return new AllocationThunker(rs, tt, usage, a);
+        try {
+            android.renderscript.Allocation a =
+                    android.renderscript.Allocation.createCubemapFromCubeFaces(
+                    rst.mN, xpos, xneg, ypos, yneg, zpos, zneg,
+                    convertMipmapControl(mips), usage);
+            TypeThunker tt = new TypeThunker(rs, a.getType());
+            return new AllocationThunker(rs, tt, usage, a);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     static public Allocation createFromBitmapResource(RenderScript rs,
@@ -281,32 +454,45 @@
                                                       int usage) {
 
         RenderScriptThunker rst = (RenderScriptThunker)rs;
-        android.renderscript.Allocation a =
-                android.renderscript.Allocation.createFromBitmapResource(
-                rst.mN, res, id, convertMipmapControl(mips), usage);
-        TypeThunker tt = new TypeThunker(rs, a.getType());
-        return new AllocationThunker(rs, tt, usage, a);
+        try {
+            android.renderscript.Allocation a =
+                    android.renderscript.Allocation.createFromBitmapResource(
+                    rst.mN, res, id, convertMipmapControl(mips), usage);
+            TypeThunker tt = new TypeThunker(rs, a.getType());
+            return new AllocationThunker(rs, tt, usage, a);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     static public Allocation createFromString(RenderScript rs,
                                               String str,
                                               int usage) {
         RenderScriptThunker rst = (RenderScriptThunker)rs;
-        android.renderscript.Allocation a =
-                android.renderscript.Allocation.createFromString(
-                rst.mN, str, usage);
-        TypeThunker tt = new TypeThunker(rs, a.getType());
-        return new AllocationThunker(rs, tt, usage, a);
+        try {
+            android.renderscript.Allocation a =
+                    android.renderscript.Allocation.createFromString(
+                    rst.mN, str, usage);
+            TypeThunker tt = new TypeThunker(rs, a.getType());
+            return new AllocationThunker(rs, tt, usage, a);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     static public Allocation createSized(RenderScript rs, Element e,
                                          int count, int usage) {
         RenderScriptThunker rst = (RenderScriptThunker)rs;
         ElementThunker et = (ElementThunker) e;
-        android.renderscript.Allocation a =
-            android.renderscript.Allocation.createSized(rst.mN, (android.renderscript.Element)e.getNObj(), count, usage);
-        TypeThunker tt = new TypeThunker(rs, a.getType());
-        return new AllocationThunker(rs, tt, usage, a);
+        try {
+            android.renderscript.Allocation a =
+                android.renderscript.Allocation.createSized
+                (rst.mN, (android.renderscript.Element)e.getNObj(), count, usage);
+            TypeThunker tt = new TypeThunker(rs, a.getType());
+            return new AllocationThunker(rs, tt, usage, a);
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
     }
 
 }
\ No newline at end of file
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ElementThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ElementThunker.java
index 508bddf..fc986b3 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ElementThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ElementThunker.java
@@ -28,11 +28,19 @@
     }
 
     public int getBytesSize() {
-        return mN.getBytesSize();
+        try {
+            return mN.getBytesSize();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public int getVectorSize() {
-        return mN.getVectorSize();
+        try {
+            return mN.getVectorSize();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     static android.renderscript.Element.DataKind convertKind(DataKind cdk) {
@@ -108,27 +116,51 @@
     }
 
     public boolean isComplex() {
-        return mN.isComplex();
+        try {
+            return mN.isComplex();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public int getSubElementCount() {
-        return mN.getSubElementCount();
+        try {
+            return mN.getSubElementCount();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Element getSubElement(int index) {
-        return new ElementThunker(mRS, mN.getSubElement(index));
+        try {
+            return new ElementThunker(mRS, mN.getSubElement(index));
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public String getSubElementName(int index) {
-        return mN.getSubElementName(index);
+        try {
+            return mN.getSubElementName(index);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public int getSubElementArraySize(int index) {
-        return mN.getSubElementArraySize(index);
+        try {
+            return mN.getSubElementArraySize(index);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public int getSubElementOffsetBytes(int index) {
-        return mN.getSubElementOffsetBytes(index);
+        try {
+            return mN.getSubElementOffsetBytes(index);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public DataType getDataType() {
@@ -148,90 +180,106 @@
 
     static Element create(RenderScript rs, DataType dt) {
         RenderScriptThunker rst = (RenderScriptThunker)rs;
-        android.renderscript.Element e = null;
-        switch(dt) {
-        case FLOAT_32:
-            e = android.renderscript.Element.F32(rst.mN);
-            break;
-        case FLOAT_64:
-            e = android.renderscript.Element.F64(rst.mN);
-            break;
-        case SIGNED_8:
-            e = android.renderscript.Element.I8(rst.mN);
-            break;
-        case SIGNED_16:
-            e = android.renderscript.Element.I16(rst.mN);
-            break;
-        case SIGNED_32:
-            e = android.renderscript.Element.I32(rst.mN);
-            break;
-        case SIGNED_64:
-            e = android.renderscript.Element.I64(rst.mN);
-            break;
-        case UNSIGNED_8:
-            e = android.renderscript.Element.U8(rst.mN);
-            break;
-        case UNSIGNED_16:
-            e = android.renderscript.Element.U16(rst.mN);
-            break;
-        case UNSIGNED_32:
-            e = android.renderscript.Element.U32(rst.mN);
-            break;
-        case UNSIGNED_64:
-            e = android.renderscript.Element.U64(rst.mN);
-            break;
-
-        case BOOLEAN:
-            e = android.renderscript.Element.BOOLEAN(rst.mN);
-            break;
-
-        case MATRIX_4X4:
-            e = android.renderscript.Element.MATRIX_4X4(rst.mN);
+        try {
+            android.renderscript.Element e = null;
+            switch(dt) {
+            case FLOAT_32:
+                e = android.renderscript.Element.F32(rst.mN);
                 break;
-        case MATRIX_3X3:
-            e = android.renderscript.Element.MATRIX_3X3(rst.mN);
-            break;
-        case MATRIX_2X2:
-            e = android.renderscript.Element.MATRIX_2X2(rst.mN);
-            break;
+            case FLOAT_64:
+                e = android.renderscript.Element.F64(rst.mN);
+                break;
+            case SIGNED_8:
+                e = android.renderscript.Element.I8(rst.mN);
+                break;
+            case SIGNED_16:
+                e = android.renderscript.Element.I16(rst.mN);
+                break;
+            case SIGNED_32:
+                e = android.renderscript.Element.I32(rst.mN);
+                break;
+            case SIGNED_64:
+                e = android.renderscript.Element.I64(rst.mN);
+                break;
+            case UNSIGNED_8:
+                e = android.renderscript.Element.U8(rst.mN);
+                break;
+            case UNSIGNED_16:
+                e = android.renderscript.Element.U16(rst.mN);
+                break;
+            case UNSIGNED_32:
+                e = android.renderscript.Element.U32(rst.mN);
+                break;
+            case UNSIGNED_64:
+                e = android.renderscript.Element.U64(rst.mN);
+                break;
 
-        case RS_ELEMENT:
-            e = android.renderscript.Element.ELEMENT(rst.mN);
-            break;
-        case RS_TYPE:
-            e = android.renderscript.Element.TYPE(rst.mN);
-            break;
-        case RS_ALLOCATION:
-            e = android.renderscript.Element.ALLOCATION(rst.mN);
-            break;
-        case RS_SAMPLER:
-            e = android.renderscript.Element.SAMPLER(rst.mN);
-            break;
-        case RS_SCRIPT:
-            e = android.renderscript.Element.SCRIPT(rst.mN);
-            break;
+            case BOOLEAN:
+                e = android.renderscript.Element.BOOLEAN(rst.mN);
+                break;
+
+            case MATRIX_4X4:
+                e = android.renderscript.Element.MATRIX_4X4(rst.mN);
+                break;
+            case MATRIX_3X3:
+                e = android.renderscript.Element.MATRIX_3X3(rst.mN);
+                break;
+            case MATRIX_2X2:
+                e = android.renderscript.Element.MATRIX_2X2(rst.mN);
+                break;
+
+            case RS_ELEMENT:
+                e = android.renderscript.Element.ELEMENT(rst.mN);
+                break;
+            case RS_TYPE:
+                e = android.renderscript.Element.TYPE(rst.mN);
+                break;
+            case RS_ALLOCATION:
+                e = android.renderscript.Element.ALLOCATION(rst.mN);
+                break;
+            case RS_SAMPLER:
+                e = android.renderscript.Element.SAMPLER(rst.mN);
+                break;
+            case RS_SCRIPT:
+                e = android.renderscript.Element.SCRIPT(rst.mN);
+                break;
+            }
+
+            return new ElementThunker(rs, e);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
         }
-
-        return new ElementThunker(rs, e);
     }
 
     public static Element createVector(RenderScript rs, DataType dt, int size) {
         RenderScriptThunker rst = (RenderScriptThunker)rs;
         android.renderscript.Element e;
-        e = android.renderscript.Element.createVector(rst.mN, convertType(dt), size);
-        return new ElementThunker(rs, e);
+        try {
+            e = android.renderscript.Element.createVector(rst.mN, convertType(dt), size);
+            return new ElementThunker(rs, e);
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
     }
 
     public static Element createPixel(RenderScript rs, DataType dt, DataKind dk) {
         RenderScriptThunker rst = (RenderScriptThunker)rs;
         android.renderscript.Element e;
-        e = android.renderscript.Element.createPixel(rst.mN, convertType(dt), convertKind(dk));
+        try {
+            e = android.renderscript.Element.createPixel(rst.mN, convertType(dt), convertKind(dk));
         return new ElementThunker(rs, e);
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
     }
 
     public boolean isCompatible(Element e) {
         ElementThunker et = (ElementThunker)e;
-        return et.mN.isCompatible(mN);
+        try {
+            return et.mN.isCompatible(mN);
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
     }
 
     static class BuilderThunker {
@@ -239,18 +287,31 @@
 
         public BuilderThunker(RenderScript rs) {
             RenderScriptThunker rst = (RenderScriptThunker)rs;
-            mN = new android.renderscript.Element.Builder(rst.mN);
+            try {
+                mN = new android.renderscript.Element.Builder(rst.mN);
+            } catch (android.renderscript.RSRuntimeException e) {
+                throw ExceptionThunker.convertException(e);
+            }
         }
 
         public void add(Element e, String name, int arraySize) {
             ElementThunker et = (ElementThunker)e;
-            mN.add(et.mN, name, arraySize);
+            try {
+                mN.add(et.mN, name, arraySize);
+            } catch (android.renderscript.RSRuntimeException exc) {
+                throw ExceptionThunker.convertException(exc);
+            }
         }
 
         public Element create(RenderScript rs) {
-            android.renderscript.Element e = mN.create();
-            return new ElementThunker(rs, e);
+            try {
+                android.renderscript.Element e = mN.create();
+                return new ElementThunker(rs, e);
+            } catch (android.renderscript.RSRuntimeException exc) {
+                throw ExceptionThunker.convertException(exc);
+            }
         }
     }
 }
 
+
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ExceptionThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ExceptionThunker.java
new file mode 100644
index 0000000..3e553b7
--- /dev/null
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ExceptionThunker.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 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.support.v8.renderscript;
+
+import java.lang.Exception;
+
+class ExceptionThunker {
+    static RuntimeException convertException (RuntimeException e) {
+        if (e instanceof android.renderscript.RSIllegalArgumentException) {
+            return new android.support.v8.renderscript.RSIllegalArgumentException(e.getMessage());
+        } else if (e instanceof android.renderscript.RSInvalidStateException) {
+            return new android.support.v8.renderscript.RSInvalidStateException(e.getMessage());
+        } else if (e instanceof android.renderscript.RSDriverException) {
+            return new android.support.v8.renderscript.RSDriverException(e.getMessage());
+        } else if (e instanceof android.renderscript.RSRuntimeException) {
+            return new android.support.v8.renderscript.RSRuntimeException(e.getMessage());
+        }
+        return e;
+    }
+
+}
\ No newline at end of file
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/RenderScriptThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/RenderScriptThunker.java
index 5ba76df..daf0b26 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/RenderScriptThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/RenderScriptThunker.java
@@ -36,8 +36,12 @@
     }
 
     public void setPriority(Priority p) {
-        if (p == Priority.LOW) mN.setPriority(android.renderscript.RenderScript.Priority.LOW);
-        if (p == Priority.NORMAL) mN.setPriority(android.renderscript.RenderScript.Priority.NORMAL);
+        try {
+            if (p == Priority.LOW) mN.setPriority(android.renderscript.RenderScript.Priority.LOW);
+            if (p == Priority.NORMAL) mN.setPriority(android.renderscript.RenderScript.Priority.NORMAL);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     RenderScriptThunker(Context ctx) {
@@ -46,21 +50,39 @@
     }
 
     public static RenderScript create(Context ctx, int sdkVersion) {
-        RenderScriptThunker rs = new RenderScriptThunker(ctx);
-        rs.mN = android.renderscript.RenderScript.create(ctx, sdkVersion);
-        return rs;
+        try {
+            RenderScriptThunker rs = new RenderScriptThunker(ctx);
+            rs.mN = android.renderscript.RenderScript.create(ctx, sdkVersion);
+            return rs;
+        }
+        catch(android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void contextDump() {
-        mN.contextDump();
+        try {
+            mN.contextDump();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void finish() {
-        mN.finish();
+        try {
+            mN.finish();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void destroy() {
-        mN.destroy();
-        mN = null;
+        try {
+            mN.destroy();
+            mN = null;
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
+
     }
 }
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/SamplerThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/SamplerThunker.java
index 56d9487..eb14c7f 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/SamplerThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/SamplerThunker.java
@@ -129,24 +129,28 @@
 
         public Sampler create() {
             mRS.validate();
-            android.renderscript.Sampler.Builder b = new android.renderscript.Sampler.Builder(mRS.mN);
-            b.setMinification(convertValue(mMin));
-            b.setMagnification(convertValue(mMag));
-            b.setWrapS(convertValue(mWrapS));
-            b.setWrapT(convertValue(mWrapT));
-            b.setAnisotropy(mAniso);
-            android.renderscript.Sampler s = b.create();
+            try {
+                android.renderscript.Sampler.Builder b = new android.renderscript.Sampler.Builder(mRS.mN);
+                b.setMinification(convertValue(mMin));
+                b.setMagnification(convertValue(mMag));
+                b.setWrapS(convertValue(mWrapS));
+                b.setWrapT(convertValue(mWrapT));
+                b.setAnisotropy(mAniso);
+                android.renderscript.Sampler s = b.create();
 
-            SamplerThunker sampler = new SamplerThunker(0, mRS);
-            sampler.mMin = mMin;
-            sampler.mMag = mMag;
-            sampler.mWrapS = mWrapS;
-            sampler.mWrapT = mWrapT;
-            sampler.mWrapR = mWrapR;
-            sampler.mAniso = mAniso;
-            sampler.mN = s;
+                SamplerThunker sampler = new SamplerThunker(0, mRS);
+                sampler.mMin = mMin;
+                sampler.mMag = mMag;
+                sampler.mWrapS = mWrapS;
+                sampler.mWrapT = mWrapT;
+                sampler.mWrapR = mWrapR;
+                sampler.mAniso = mAniso;
+                sampler.mN = s;
 
-            return sampler;
+                return sampler;
+            } catch (android.renderscript.RSRuntimeException e) {
+                throw ExceptionThunker.convertException(e);
+            }
         }
     }
 
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptCThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptCThunker.java
index ba6a075..2dd9ae9 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptCThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptCThunker.java
@@ -50,12 +50,21 @@
         if (eout != null) {
             neout = ((ElementThunker)eout).mN;
         }
-        return createKernelID(slot, sig, nein, neout);
+        try {
+            android.renderscript.Script.KernelID kid = createKernelID(slot, sig, nein, neout);
+            return kid;
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
 
     void thunkInvoke(int slot) {
-        invoke(slot);
+        try {
+            invoke(slot);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     void thunkBindAllocation(Allocation va, int slot) {
@@ -63,17 +72,29 @@
         if (va != null) {
             nva = ((AllocationThunker)va).mN;
         }
-        bindAllocation(nva, slot);
+        try {
+            bindAllocation(nva, slot);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     void thunkSetTimeZone(String timeZone) {
-        setTimeZone(timeZone);
+        try {
+            setTimeZone(timeZone);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     void thunkInvoke(int slot, FieldPacker v) {
-        android.renderscript.FieldPacker nfp =
+        try {
+            android.renderscript.FieldPacker nfp =
                 new android.renderscript.FieldPacker(v.getData());
-        invoke(slot, nfp);
+            invoke(slot, nfp);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     void thunkForEach(int slot, Allocation ain, Allocation aout, FieldPacker v) {
@@ -86,76 +107,124 @@
         if (aout != null) {
             nout = ((AllocationThunker)aout).mN;
         }
-        if (v != null) {
-            nfp = new android.renderscript.FieldPacker(v.getData());
+        try {
+            if (v != null) {
+                nfp = new android.renderscript.FieldPacker(v.getData());
+            }
+            forEach(slot, nin, nout, nfp);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
         }
-        forEach(slot, nin, nout, nfp);
     }
 
     void thunkForEach(int slot, Allocation ain, Allocation aout, FieldPacker v,
                       android.support.v8.renderscript.Script.LaunchOptions sc) {
-        android.renderscript.Script.LaunchOptions lo = null;
-        if (sc != null) {
-            lo = new android.renderscript.Script.LaunchOptions();
-            if (sc.getXEnd() > 0) lo.setX(sc.getXStart(), sc.getXEnd());
-            if (sc.getYEnd() > 0) lo.setY(sc.getYStart(), sc.getYEnd());
-            if (sc.getZEnd() > 0) lo.setZ(sc.getZStart(), sc.getZEnd());
-        }
+        try {
+            android.renderscript.Script.LaunchOptions lo = null;
+            if (sc != null) {
+                lo = new android.renderscript.Script.LaunchOptions();
+                if (sc.getXEnd() > 0) lo.setX(sc.getXStart(), sc.getXEnd());
+                if (sc.getYEnd() > 0) lo.setY(sc.getYStart(), sc.getYEnd());
+                if (sc.getZEnd() > 0) lo.setZ(sc.getZStart(), sc.getZEnd());
+            }
 
-        android.renderscript.Allocation nin = null;
-        android.renderscript.Allocation nout = null;
-        android.renderscript.FieldPacker nfp = null;
-        if (ain != null) {
-            nin = ((AllocationThunker)ain).mN;
+            android.renderscript.Allocation nin = null;
+            android.renderscript.Allocation nout = null;
+            android.renderscript.FieldPacker nfp = null;
+            if (ain != null) {
+                nin = ((AllocationThunker)ain).mN;
+            }
+            if (aout != null) {
+                nout = ((AllocationThunker)aout).mN;
+            }
+            if (v != null) {
+                nfp = new android.renderscript.FieldPacker(v.getData());
+            }
+            forEach(slot, nin, nout, nfp, lo);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
         }
-        if (aout != null) {
-            nout = ((AllocationThunker)aout).mN;
-        }
-        if (v != null) {
-            nfp = new android.renderscript.FieldPacker(v.getData());
-        }
-        forEach(slot, nin, nout, nfp, lo);
     }
 
     void thunkSetVar(int index, float v) {
-        setVar(index, v);
+        try {
+            setVar(index, v);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     void thunkSetVar(int index, double v) {
-        setVar(index, v);
+        try {
+            setVar(index, v);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     void thunkSetVar(int index, int v) {
-        setVar(index, v);
+        try {
+            setVar(index, v);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     void thunkSetVar(int index, long v) {
-        setVar(index, v);
+        try {
+            setVar(index, v);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     void thunkSetVar(int index, boolean v) {
-        setVar(index, v);
+        try {
+            setVar(index, v);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     void thunkSetVar(int index, BaseObj o) {
         if (o == null) {
-            setVar(index, 0);
+            try {
+                setVar(index, 0);
+            } catch (android.renderscript.RSRuntimeException e) {
+                throw ExceptionThunker.convertException(e);
+            }
             return;
         }
-        setVar(index, o.getNObj());
+        try {
+            setVar(index, o.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
     void thunkSetVar(int index, FieldPacker v) {
-        android.renderscript.FieldPacker nfp =
+        try {
+            android.renderscript.FieldPacker nfp =
                 new android.renderscript.FieldPacker(v.getData());
-        setVar(index, nfp);
+            setVar(index, nfp);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     void thunkSetVar(int index, FieldPacker v, Element e, int[] dims) {
-        android.renderscript.FieldPacker nfp =
+        try {
+            android.renderscript.FieldPacker nfp =
                 new android.renderscript.FieldPacker(v.getData());
-        ElementThunker et = (ElementThunker)e;
-        setVar(index, nfp, et.mN, dims);
+            ElementThunker et = (ElementThunker)e;
+            setVar(index, nfp, et.mN, dims);
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
     }
 
     android.renderscript.Script.FieldID thunkCreateFieldID(int slot, Element e) {
-        ElementThunker et = (ElementThunker) e;
-        return createFieldID(slot, et.getNObj());
+        try {
+            ElementThunker et = (ElementThunker) e;
+            return createFieldID(slot, et.getNObj());
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
     }
 
 }
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptGroupThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptGroupThunker.java
index f6e8bc4..588d674 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptGroupThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptGroupThunker.java
@@ -32,16 +32,28 @@
 
     public void setInput(Script.KernelID s, Allocation a) {
         AllocationThunker at = (AllocationThunker) a;
-        mN.setInput(s.mN, at.getNObj());
+        try {
+            mN.setInput(s.mN, at.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void setOutput(Script.KernelID s, Allocation a) {
         AllocationThunker at = (AllocationThunker) a;
-        mN.setOutput(s.mN, at.getNObj());
+        try {
+            mN.setOutput(s.mN, at.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void execute() {
-        mN.execute();
+        try {
+            mN.execute();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
 
@@ -53,23 +65,39 @@
         Builder(RenderScript rs) {
             RenderScriptThunker rst = (RenderScriptThunker) rs;
             mRS = rs;
-            bN = new android.renderscript.ScriptGroup.Builder(rst.mN);
+            try {
+                bN = new android.renderscript.ScriptGroup.Builder(rst.mN);
+            } catch (android.renderscript.RSRuntimeException e) {
+                throw ExceptionThunker.convertException(e);
+            }
         }
 
         public Builder addKernel(Script.KernelID k) {
-            bN.addKernel(k.mN);
+            try {
+                bN.addKernel(k.mN);
+            } catch (android.renderscript.RSRuntimeException e) {
+                throw ExceptionThunker.convertException(e);
+            }
             return this;
         }
 
         public Builder addConnection(Type t, Script.KernelID from, Script.FieldID to) {
             TypeThunker tt = (TypeThunker) t;
-            bN.addConnection(tt.getNObj(), from.mN, to.mN);
+            try {
+                bN.addConnection(tt.getNObj(), from.mN, to.mN);
+            } catch (android.renderscript.RSRuntimeException e) {
+                throw ExceptionThunker.convertException(e);
+            }
             return this;
         }
 
         public Builder addConnection(Type t, Script.KernelID from, Script.KernelID to) {
             TypeThunker tt = (TypeThunker) t;
-            bN.addConnection(tt.getNObj(), from.mN, to.mN);
+            try {
+                bN.addConnection(tt.getNObj(), from.mN, to.mN);
+            } catch (android.renderscript.RSRuntimeException e) {
+                throw ExceptionThunker.convertException(e);
+            }
             return this;
         }
 
@@ -77,7 +105,11 @@
 
         public ScriptGroupThunker create() {
             ScriptGroupThunker sg = new ScriptGroupThunker(0, mRS);
-            sg.mN = bN.create();
+            try {
+                sg.mN = bN.create();
+            } catch (android.renderscript.RSRuntimeException e) {
+                throw ExceptionThunker.convertException(e);
+            }
             return sg;
         }
     }
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic3DLUTThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic3DLUTThunker.java
index ce11a4d..a1c6ada 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic3DLUTThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsic3DLUTThunker.java
@@ -38,13 +38,21 @@
         ElementThunker et = (ElementThunker) e;
 
         ScriptIntrinsic3DLUTThunker lut = new ScriptIntrinsic3DLUTThunker(0, rs, e);
-        lut.mN = android.renderscript.ScriptIntrinsic3DLUT.create(rst.mN, et.getNObj());
+        try {
+            lut.mN = android.renderscript.ScriptIntrinsic3DLUT.create(rst.mN, et.getNObj());
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
         return lut;
     }
 
     public void setLUT(Allocation lut) {
         AllocationThunker lutt = (AllocationThunker) lut;
-        mN.setLUT(lutt.getNObj());
+        try {
+            mN.setLUT(lutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
 
@@ -58,7 +66,11 @@
     public void forEach(Allocation ain, Allocation aout) {
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
-        mN.forEach(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEach(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     /**
@@ -68,7 +80,11 @@
      */
     public Script.KernelID getKernelID() {
         Script.KernelID k = createKernelID(0, 3, null, null);
-        k.mN = mN.getKernelID();
+        try {
+            k.mN = mN.getKernelID();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 }
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicBlendThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicBlendThunker.java
index 2836034f..7c70934 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicBlendThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicBlendThunker.java
@@ -32,7 +32,11 @@
         ElementThunker et = (ElementThunker)e;
 
         ScriptIntrinsicBlendThunker blend = new ScriptIntrinsicBlendThunker(0, rs);
-        blend.mN = android.renderscript.ScriptIntrinsicBlend.create(rst.mN, et.getNObj());
+        try {
+            blend.mN = android.renderscript.ScriptIntrinsicBlend.create(rst.mN, et.getNObj());
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
         return blend;
     }
 
@@ -40,12 +44,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachClear(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachClear(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDClear() {
         Script.KernelID k = createKernelID(0, 3, null, null);
-        k.mN = mN.getKernelIDClear();
+        try {
+            k.mN = mN.getKernelIDClear();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -53,12 +65,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachSrc(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachSrc(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDSrc() {
         Script.KernelID k = createKernelID(1, 3, null, null);
-        k.mN = mN.getKernelIDSrc();
+        try {
+            k.mN = mN.getKernelIDSrc();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -66,12 +86,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachDst(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachDst(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDDst() {
         Script.KernelID k = createKernelID(2, 3, null, null);
-        k.mN = mN.getKernelIDDst();
+        try {
+            k.mN = mN.getKernelIDDst();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -79,12 +107,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachSrcOver(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachSrcOver(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDSrcOver() {
         Script.KernelID k = createKernelID(3, 3, null, null);
-        k.mN = mN.getKernelIDSrcOver();
+        try {
+            k.mN = mN.getKernelIDSrcOver();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -92,12 +128,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachDstOver(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachDstOver(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDDstOver() {
         Script.KernelID k = createKernelID(4, 3, null, null);
-        k.mN = mN.getKernelIDDstOver();
+        try {
+            k.mN = mN.getKernelIDDstOver();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -105,12 +149,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachSrcIn(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachSrcIn(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDSrcIn() {
         Script.KernelID k = createKernelID(5, 3, null, null);
-        k.mN = mN.getKernelIDSrcIn();
+        try {
+            k.mN = mN.getKernelIDSrcIn();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -118,12 +170,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachDstIn(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachDstIn(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDDstIn() {
         Script.KernelID k = createKernelID(6, 3, null, null);
-        k.mN = mN.getKernelIDDstIn();
+        try {
+            k.mN = mN.getKernelIDDstIn();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -131,12 +191,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachSrcOut(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachSrcOut(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDSrcOut() {
         Script.KernelID k = createKernelID(7, 3, null, null);
-        k.mN = mN.getKernelIDSrcOut();
+        try {
+            k.mN = mN.getKernelIDSrcOut();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -144,12 +212,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachDstOut(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachDstOut(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDDstOut() {
         Script.KernelID k = createKernelID(8, 3, null, null);
-        k.mN = mN.getKernelIDDstOut();
+        try {
+            k.mN = mN.getKernelIDDstOut();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -157,12 +233,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachSrcAtop(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachSrcAtop(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDSrcAtop() {
         Script.KernelID k = createKernelID(9, 3, null, null);
-        k.mN = mN.getKernelIDSrcAtop();
+        try {
+            k.mN = mN.getKernelIDSrcAtop();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -170,12 +254,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachDstAtop(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachDstAtop(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDDstAtop() {
         Script.KernelID k = createKernelID(10, 3, null, null);
-        k.mN = mN.getKernelIDDstAtop();
+        try {
+            k.mN = mN.getKernelIDDstAtop();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -183,12 +275,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachXor(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachXor(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDXor() {
         Script.KernelID k = createKernelID(11, 3, null, null);
-        k.mN = mN.getKernelIDXor();
+        try {
+            k.mN = mN.getKernelIDXor();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -196,12 +296,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachMultiply(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachMultiply(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDMultiply() {
         Script.KernelID k = createKernelID(14, 3, null, null);
-        k.mN = mN.getKernelIDMultiply();
+        try {
+            k.mN = mN.getKernelIDMultiply();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -209,12 +317,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachAdd(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachAdd(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDAdd() {
         Script.KernelID k = createKernelID(34, 3, null, null);
-        k.mN = mN.getKernelIDAdd();
+        try {
+            k.mN = mN.getKernelIDAdd();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
@@ -222,12 +338,20 @@
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
 
-        mN.forEachSubtract(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEachSubtract(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelIDSubtract() {
         Script.KernelID k = createKernelID(35, 3, null, null);
-        k.mN = mN.getKernelIDSubtract();
+        try {
+            k.mN = mN.getKernelIDSubtract();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicBlurThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicBlurThunker.java
index 9be99cb..31e22bb 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicBlurThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicBlurThunker.java
@@ -37,35 +37,59 @@
         ElementThunker et = (ElementThunker) e;
 
         ScriptIntrinsicBlurThunker blur = new ScriptIntrinsicBlurThunker(0, rs);
-        blur.mN = android.renderscript.ScriptIntrinsicBlur.create(rst.mN, et.getNObj());
+        try {
+            blur.mN = android.renderscript.ScriptIntrinsicBlur.create(rst.mN, et.getNObj());
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
         return blur;
     }
 
     public void setInput(Allocation ain) {
         AllocationThunker aint = (AllocationThunker) ain;
-        mN.setInput(aint.getNObj());
+        try {
+            mN.setInput(aint.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void setRadius(float radius) {
-        mN.setRadius(radius);
+        try {
+            mN.setRadius(radius);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void forEach(Allocation aout) {
         AllocationThunker aoutt = (AllocationThunker) aout;
         if (aoutt != null) {
-            mN.forEach(aoutt.getNObj());
+            try {
+                mN.forEach(aoutt.getNObj());
+            } catch (android.renderscript.RSRuntimeException e) {
+                throw ExceptionThunker.convertException(e);
+            }
         }
     }
 
     public Script.KernelID getKernelID() {
         Script.KernelID k = createKernelID(0, 2, null, null);
-        k.mN = mN.getKernelID();
+        try {
+            k.mN = mN.getKernelID();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
     public Script.FieldID getFieldID_Input() {
         Script.FieldID f = createFieldID(1, null);
-        f.mN = mN.getFieldID_Input();
+        try {
+            f.mN = mN.getFieldID_Input();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return f;
     }
 }
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicColorMatrixThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicColorMatrixThunker.java
index 28c2a7b..797c0e7 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicColorMatrixThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicColorMatrixThunker.java
@@ -34,41 +34,73 @@
         ElementThunker et = (ElementThunker)e;
 
         ScriptIntrinsicColorMatrixThunker cm =  new ScriptIntrinsicColorMatrixThunker(0, rs);
-        cm.mN = android.renderscript.ScriptIntrinsicColorMatrix.create(rst.mN, et.getNObj());
+        try {
+            cm.mN = android.renderscript.ScriptIntrinsicColorMatrix.create(rst.mN, et.getNObj());
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
         return cm;
 
     }
 
     public void setColorMatrix(Matrix4f m) {
-        mN.setColorMatrix(new android.renderscript.Matrix4f(m.getArray()));
+        try {
+            mN.setColorMatrix(new android.renderscript.Matrix4f(m.getArray()));
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void setColorMatrix(Matrix3f m) {
-        mN.setColorMatrix(new android.renderscript.Matrix3f(m.getArray()));
+        try {
+            mN.setColorMatrix(new android.renderscript.Matrix3f(m.getArray()));
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void setGreyscale() {
-        mN.setGreyscale();
+        try {
+            mN.setGreyscale();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void setYUVtoRGB() {
-        mN.setYUVtoRGB();
+        try {
+            mN.setYUVtoRGB();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void setRGBtoYUV() {
-        mN.setRGBtoYUV();
+        try {
+            mN.setRGBtoYUV();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
 
     public void forEach(Allocation ain, Allocation aout) {
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
-        mN.forEach(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEach(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelID() {
         Script.KernelID k = createKernelID(0, 3, null, null);
-        k.mN = mN.getKernelID();
+        try {
+            k.mN = mN.getKernelID();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicConvolve3x3Thunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicConvolve3x3Thunker.java
index 2645fbf..fa997c1 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicConvolve3x3Thunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicConvolve3x3Thunker.java
@@ -35,34 +35,58 @@
         ElementThunker et = (ElementThunker) e;
 
         ScriptIntrinsicConvolve3x3Thunker si = new ScriptIntrinsicConvolve3x3Thunker(0, rs);
-        si.mN = android.renderscript.ScriptIntrinsicConvolve3x3.create(rst.mN, et.getNObj());
+        try {
+            si.mN = android.renderscript.ScriptIntrinsicConvolve3x3.create(rst.mN, et.getNObj());
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
         return si;
     }
 
     public void setInput(Allocation ain) {
         AllocationThunker aint = (AllocationThunker)ain;
-        mN.setInput(aint.getNObj());
+        try {
+            mN.setInput(aint.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void setCoefficients(float v[]) {
-        mN.setCoefficients(v);
+        try {
+            mN.setCoefficients(v);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void forEach(Allocation aout) {
         AllocationThunker aoutt = (AllocationThunker)aout;
-        mN.forEach(aoutt.getNObj());
+        try {
+            mN.forEach(aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
 
     }
 
     public Script.KernelID getKernelID() {
         Script.KernelID k = createKernelID(0, 2, null, null);
-        k.mN = mN.getKernelID();
+        try {
+            k.mN = mN.getKernelID();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
     public Script.FieldID getFieldID_Input() {
         Script.FieldID f = createFieldID(1, null);
-        f.mN = mN.getFieldID_Input();
+        try {
+            f.mN = mN.getFieldID_Input();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return f;
     }
 
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicConvolve5x5Thunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicConvolve5x5Thunker.java
index 4430f9e..2071ddd 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicConvolve5x5Thunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicConvolve5x5Thunker.java
@@ -35,34 +35,58 @@
         ElementThunker et = (ElementThunker) e;
 
         ScriptIntrinsicConvolve5x5Thunker si = new ScriptIntrinsicConvolve5x5Thunker(0, rs);
-        si.mN = android.renderscript.ScriptIntrinsicConvolve5x5.create(rst.mN, et.getNObj());
+        try {
+            si.mN = android.renderscript.ScriptIntrinsicConvolve5x5.create(rst.mN, et.getNObj());
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
         return si;
     }
 
     public void setInput(Allocation ain) {
         AllocationThunker aint = (AllocationThunker)ain;
-        mN.setInput(aint.getNObj());
+        try {
+            mN.setInput(aint.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void setCoefficients(float v[]) {
-        mN.setCoefficients(v);
+        try {
+            mN.setCoefficients(v);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void forEach(Allocation aout) {
         AllocationThunker aoutt = (AllocationThunker)aout;
-        mN.forEach(aoutt.getNObj());
+        try {
+            mN.forEach(aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
 
     }
 
     public Script.KernelID getKernelID() {
         Script.KernelID k = createKernelID(0, 2, null, null);
-        k.mN = mN.getKernelID();
+        try {
+            k.mN = mN.getKernelID();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
     public Script.FieldID getFieldID_Input() {
         Script.FieldID f = createFieldID(1, null);
-        f.mN = mN.getFieldID_Input();
+        try {
+            f.mN = mN.getFieldID_Input();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return f;
     }
 
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicLUTThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicLUTThunker.java
index 547b679..ecd17f2 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicLUTThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicLUTThunker.java
@@ -34,35 +34,63 @@
         ElementThunker et = (ElementThunker) e;
 
         ScriptIntrinsicLUTThunker si = new ScriptIntrinsicLUTThunker(0, rs);
-        si.mN = android.renderscript.ScriptIntrinsicLUT.create(rst.mN, et.getNObj());
+        try {
+            si.mN = android.renderscript.ScriptIntrinsicLUT.create(rst.mN, et.getNObj());
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
         return si;
     }
 
     public void setRed(int index, int value) {
-        mN.setRed(index, value);
+        try {
+            mN.setRed(index, value);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void setGreen(int index, int value) {
-        mN.setGreen(index, value);
+        try {
+            mN.setGreen(index, value);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void setBlue(int index, int value) {
-        mN.setBlue(index, value);
+        try {
+            mN.setBlue(index, value);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void setAlpha(int index, int value) {
-        mN.setAlpha(index, value);
+        try {
+            mN.setAlpha(index, value);
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void forEach(Allocation ain, Allocation aout) {
         AllocationThunker aint = (AllocationThunker)ain;
         AllocationThunker aoutt = (AllocationThunker)aout;
-        mN.forEach(aint.getNObj(), aoutt.getNObj());
+        try {
+            mN.forEach(aint.getNObj(), aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelID() {
         Script.KernelID k = createKernelID(0, 3, null, null);
-        k.mN = mN.getKernelID();
+        try {
+            k.mN = mN.getKernelID();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 }
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicYuvToRGBThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicYuvToRGBThunker.java
index be97392..dd75591c 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicYuvToRGBThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/ScriptIntrinsicYuvToRGBThunker.java
@@ -34,30 +34,50 @@
         ElementThunker et = (ElementThunker) e;
 
         ScriptIntrinsicYuvToRGBThunker si = new ScriptIntrinsicYuvToRGBThunker(0, rs);
-        si.mN = android.renderscript.ScriptIntrinsicYuvToRGB.create(rst.mN, et.getNObj());
+        try {
+            si.mN = android.renderscript.ScriptIntrinsicYuvToRGB.create(rst.mN, et.getNObj());
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
         return si;
     }
 
 
     public void setInput(Allocation ain) {
         AllocationThunker aint = (AllocationThunker)ain;
-        mN.setInput(aint.getNObj());
+        try {
+            mN.setInput(aint.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public void forEach(Allocation aout) {
         AllocationThunker aoutt = (AllocationThunker)aout;
-        mN.forEach(aoutt.getNObj());
+        try {
+            mN.forEach(aoutt.getNObj());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
     }
 
     public Script.KernelID getKernelID() {
         Script.KernelID k = createKernelID(0, 2, null, null);
-        k.mN = mN.getKernelID();
+        try {
+            k.mN = mN.getKernelID();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return k;
     }
 
     public Script.FieldID getFieldID_Input() {
         Script.FieldID f = createFieldID(0, null);
-        f.mN = mN.getFieldID_Input();
+        try {
+            f.mN = mN.getFieldID_Input();
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
         return f;
     }
 }
diff --git a/v8/renderscript/java/src/android/support/v8/renderscript/TypeThunker.java b/v8/renderscript/java/src/android/support/v8/renderscript/TypeThunker.java
index 279d9ba8..557c545 100644
--- a/v8/renderscript/java/src/android/support/v8/renderscript/TypeThunker.java
+++ b/v8/renderscript/java/src/android/support/v8/renderscript/TypeThunker.java
@@ -42,8 +42,12 @@
     TypeThunker(RenderScript rs, android.renderscript.Type t) {
         super(0, rs);
         mN = t;
-        internalCalc();
-        mElement = new ElementThunker(rs, t.getElement());
+        try {
+            internalCalc();
+            mElement = new ElementThunker(rs, t.getElement());
+        } catch (android.renderscript.RSRuntimeException e) {
+            throw ExceptionThunker.convertException(e);
+        }
 
         synchronized(mMap) {
             mMap.put(mN, this);
@@ -58,18 +62,22 @@
                        int dx, int dy, int dz, boolean dmip, boolean dfaces, int yuv) {
         ElementThunker et = (ElementThunker)e;
         RenderScriptThunker rst = (RenderScriptThunker)rs;
-        android.renderscript.Type.Builder tb =
-            new android.renderscript.Type.Builder(rst.mN, et.mN);
-        if (dx > 0) tb.setX(dx);
-        if (dy > 0) tb.setY(dy);
-        if (dz > 0) tb.setZ(dz);
-        if (dmip) tb.setMipmaps(dmip);
-        if (dfaces) tb.setFaces(dfaces);
-        if (yuv > 0) tb.setYuvFormat(yuv);
-        android.renderscript.Type nt = tb.create();
-        TypeThunker tt = new TypeThunker(rs, nt);
-        tt.internalCalc();
+        try {
+            android.renderscript.Type.Builder tb =
+                new android.renderscript.Type.Builder(rst.mN, et.mN);
+            if (dx > 0) tb.setX(dx);
+            if (dy > 0) tb.setY(dy);
+            if (dz > 0) tb.setZ(dz);
+            if (dmip) tb.setMipmaps(dmip);
+            if (dfaces) tb.setFaces(dfaces);
+            if (yuv > 0) tb.setYuvFormat(yuv);
+            android.renderscript.Type nt = tb.create();
+            TypeThunker tt = new TypeThunker(rs, nt);
+            tt.internalCalc();
 
-        return tt;
+            return tt;
+        } catch (android.renderscript.RSRuntimeException exc) {
+            throw ExceptionThunker.convertException(exc);
+        }
     }
 }