Merge "protect all /cache/recovery/last_* files from deletion"
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 1b4ef0d..ebe403b 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -16,6 +16,9 @@
 
 package android.app;
 
+import com.android.internal.app.IUsageStats;
+import com.android.internal.os.PkgUsageStats;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -26,17 +29,15 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.os.Debug;
-import android.os.RemoteException;
 import android.os.Handler;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.Log;
-import com.android.internal.app.IUsageStats;
-import com.android.internal.os.PkgUsageStats;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -676,7 +677,7 @@
     public List<RunningServiceInfo> getRunningServices(int maxNum)
             throws SecurityException {
         try {
-            return (List<RunningServiceInfo>)ActivityManagerNative.getDefault()
+            return ActivityManagerNative.getDefault()
                     .getServices(maxNum, 0);
         } catch (RemoteException e) {
             // System dead, we will be dead too soon!
@@ -1331,4 +1332,17 @@
             return new HashMap<String, Integer>();
         }
     }
+
+    /**
+     * @param userid the user's id. Zero indicates the default user 
+     * @hide
+     */
+    public boolean switchUser(int userid) {
+        try {
+            return ActivityManagerNative.getDefault().switchUser(userid);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
 }
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 5fbc70f..d41c2d0 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1397,6 +1397,15 @@
             return true;
         }
 
+        case SWITCH_USER_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            int userid = data.readInt();
+            boolean result = switchUser(userid);
+            reply.writeNoException();
+            reply.writeInt(result ? 1 : 0);
+            return true;
+        }
+
         }
 
         return super.onTransact(code, data, reply, flags);
@@ -3141,5 +3150,18 @@
         return result;
     }
 
+    public boolean switchUser(int userid) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeInt(userid);
+        mRemote.transact(SWITCH_USER_TRANSACTION, data, reply, 0);
+        reply.readException();
+        boolean result = reply.readInt() != 0;
+        reply.recycle();
+        data.recycle();
+        return result;
+    }
+
     private IBinder mRemote;
 }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 50e56c7..ef8ba8e 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -33,13 +33,13 @@
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManager;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
@@ -1106,6 +1106,56 @@
         return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
     }
 
+    // Multi-user support
+
+    /**
+     * @hide
+     */
+    @Override
+    public UserInfo createUser(String name, int flags) {
+        // TODO
+        return null;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public List<UserInfo> getUsers() {
+        // TODO:
+        // Dummy code, always returns just the primary user
+        ArrayList<UserInfo> users = new ArrayList<UserInfo>();
+        UserInfo primary = new UserInfo(0, "Root!",
+                UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
+        users.add(primary);
+        return users;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean removeUser(int id) {
+        // TODO:
+        return false;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void updateUserName(int id, String name) {
+        // TODO:
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void updateUserFlags(int id, int flags) {
+        // TODO:
+    }
+
     private final ContextImpl mContext;
     private final IPackageManager mPM;
 
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index cd26a62..5a15b08 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -342,6 +342,9 @@
     public int startActivitiesInPackage(int uid,
             Intent[] intents, String[] resolvedTypes, IBinder resultTo) throws RemoteException;
 
+    // Multi-user APIs
+    public boolean switchUser(int userid) throws RemoteException;
+
     /*
      * Private non-Binder interfaces
      */
@@ -557,4 +560,5 @@
     int START_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+120;
     int START_ACTIVITIES_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+121;
     int ACTIVITY_SLEPT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+122;
+    int SWITCH_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+123;
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 80bed0d..99c4c7f 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -150,21 +150,21 @@
      * {@link PackageInfo#permissions}.
      */
     public static final int GET_PERMISSIONS               = 0x00001000;
-    
+
     /**
      * Flag parameter to retrieve all applications(even uninstalled ones) with data directories.
-     * This state could have resulted if applications have been deleted with flag 
+     * This state could have resulted if applications have been deleted with flag
      * DONT_DELETE_DATA
      * with a possibility of being replaced or reinstalled in future
      */
     public static final int GET_UNINSTALLED_PACKAGES = 0x00002000;
-    
+
     /**
      * {@link PackageInfo} flag: return information about
      * hardware preferences in
      * {@link PackageInfo#configPreferences PackageInfo.configPreferences} and
      * requested features in {@link PackageInfo#reqFeatures
-     * PackageInfo.reqFeatures}. 
+     * PackageInfo.reqFeatures}.
      */
     public static final int GET_CONFIGURATIONS = 0x00004000;
 
@@ -244,7 +244,7 @@
     public static final int INSTALL_REPLACE_EXISTING = 0x00000002;
 
     /**
-     * Flag parameter for {@link #installPackage} to indicate that you want to 
+     * Flag parameter for {@link #installPackage} to indicate that you want to
      * allow test packages (those that have set android:testOnly in their
      * manifest) to be installed.
      * @hide
@@ -555,7 +555,7 @@
      * Return code for when package deletion succeeds. This is passed to the
      * {@link IPackageDeleteObserver} by {@link #deletePackage()} if the system
      * succeeded in deleting the package.
-     * 
+     *
      * @hide
      */
     public static final int DELETE_SUCCEEDED = 1;
@@ -564,7 +564,7 @@
      * Deletion failed return code: this is passed to the
      * {@link IPackageDeleteObserver} by {@link #deletePackage()} if the system
      * failed to delete the package for an unspecified reason.
-     * 
+     *
      * @hide
      */
     public static final int DELETE_FAILED_INTERNAL_ERROR = -1;
@@ -574,7 +574,7 @@
      * {@link IPackageDeleteObserver} by {@link #deletePackage()} if the system
      * failed to delete the package because it is the active DevicePolicy
      * manager.
-     * 
+     *
      * @hide
      */
     public static final int DELETE_FAILED_DEVICE_POLICY_MANAGER = -2;
@@ -583,7 +583,7 @@
      * Return code that is passed to the {@link IPackageMoveObserver} by
      * {@link #movePackage(android.net.Uri, IPackageMoveObserver)} when the
      * package has been successfully moved by the system.
-     * 
+     *
      * @hide
      */
     public static final int MOVE_SUCCEEDED = 1;
@@ -641,7 +641,7 @@
      * {@link #movePackage(android.net.Uri, IPackageMoveObserver)} if the
      * specified package already has an operation pending in the
      * {@link PackageHandler} queue.
-     * 
+     *
      * @hide
      */
     public static final int MOVE_FAILED_OPERATION_PENDING = -7;
@@ -789,7 +789,7 @@
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_SENSOR_PROXIMITY = "android.hardware.sensor.proximity";
-    
+
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device has a telephony radio with data
@@ -797,14 +797,14 @@
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_TELEPHONY = "android.hardware.telephony";
-    
+
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device has a CDMA telephony stack.
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
-    
+
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device has a GSM telephony stack.
@@ -847,8 +847,8 @@
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_TOUCHSCREEN = "android.hardware.touchscreen";
-    
-    
+
+
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device's touch screen supports
@@ -856,7 +856,7 @@
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_TOUCHSCREEN_MULTITOUCH = "android.hardware.touchscreen.multitouch";
-    
+
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device's touch screen is capable of
@@ -932,11 +932,11 @@
      * @return Returns a PackageInfo object containing information about the package.
      *         If flag GET_UNINSTALLED_PACKAGES is set and  if the package is not
      *         found in the list of installed applications, the package information is
-     *         retrieved from the list of uninstalled applications(which includes 
+     *         retrieved from the list of uninstalled applications(which includes
      *         installed applications as well as applications
      *         with data directory ie applications which had been
      *         deleted with DONT_DELTE_DATA flag set).
-     *         
+     *
      * @see #GET_ACTIVITIES
      * @see #GET_GIDS
      * @see #GET_CONFIGURATIONS
@@ -947,7 +947,7 @@
      * @see #GET_SERVICES
      * @see #GET_SIGNATURES
      * @see #GET_UNINSTALLED_PACKAGES
-     *                  
+     *
      */
     public abstract PackageInfo getPackageInfo(String packageName, int flags)
             throws NameNotFoundException;
@@ -960,7 +960,7 @@
      * the canonical name for each package.
      */
     public abstract String[] currentToCanonicalPackageNames(String[] names);
-    
+
     /**
      * Map from a packages canonical name to the current name in use on the device.
      * @param names Array of new names to be mapped.
@@ -968,7 +968,7 @@
      * the current name for each package.
      */
     public abstract String[] canonicalToCurrentPackageNames(String[] names);
-    
+
     /**
      * Return a "good" intent to launch a front-door activity in a package,
      * for use for example to implement an "open" button when browsing through
@@ -976,12 +976,12 @@
      * activity in the category {@link Intent#CATEGORY_INFO}, next for a
      * main activity in the category {@link Intent#CATEGORY_LAUNCHER}, or return
      * null if neither are found.
-     * 
+     *
      * <p>Throws {@link NameNotFoundException} if a package with the given
      * name can not be found on the system.
      *
      * @param packageName The name of the package to inspect.
-     * 
+     *
      * @return Returns either a fully-qualified Intent that can be used to
      * launch the main activity in the package, or null if the package does
      * not contain such an activity.
@@ -1077,16 +1077,16 @@
      *
      * @param packageName The full name (i.e. com.google.apps.contacts) of an
      *                    application.
-     * @param flags Additional option flags. Use any combination of 
+     * @param flags Additional option flags. Use any combination of
      * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
      * {@link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
      *
-     * @return  {@link ApplicationInfo} Returns ApplicationInfo object containing 
+     * @return  {@link ApplicationInfo} Returns ApplicationInfo object containing
      *         information about the package.
      *         If flag GET_UNINSTALLED_PACKAGES is set and  if the package is not
-     *         found in the list of installed applications, 
-     *         the application information is retrieved from the 
-     *         list of uninstalled applications(which includes 
+     *         found in the list of installed applications,
+     *         the application information is retrieved from the
+     *         list of uninstalled applications(which includes
      *         installed applications as well as applications
      *         with data directory ie applications which had been
      *         deleted with DONT_DELTE_DATA flag set).
@@ -1108,7 +1108,7 @@
      * @param component The full component name (i.e.
      * com.google.apps.contacts/com.google.apps.contacts.ContactsList) of an Activity
      * class.
-     * @param flags Additional option flags. Use any combination of 
+     * @param flags Additional option flags. Use any combination of
      * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
      * to modify the data (in ApplicationInfo) returned.
      *
@@ -1131,7 +1131,7 @@
      * @param component The full component name (i.e.
      * com.google.apps.calendar/com.google.apps.calendar.CalendarAlarm) of a Receiver
      * class.
-     * @param flags Additional option flags.  Use any combination of 
+     * @param flags Additional option flags.  Use any combination of
      * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
      * to modify the data returned.
      *
@@ -1154,12 +1154,12 @@
      * @param component The full component name (i.e.
      * com.google.apps.media/com.google.apps.media.BackgroundPlayback) of a Service
      * class.
-     * @param flags Additional option flags.  Use any combination of 
+     * @param flags Additional option flags.  Use any combination of
      * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
      * to modify the data returned.
      *
      * @return ServiceInfo containing information about the service.
-     * 
+     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      */
@@ -1206,7 +1206,7 @@
      *
      * @return A List of PackageInfo objects, one for each package that is
      *         installed on the device.  In the unlikely case of there being no
-     *         installed packages, an empty list is returned. 
+     *         installed packages, an empty list is returned.
      *         If flag GET_UNINSTALLED_PACKAGES is set, a list of all
      *         applications including those deleted with DONT_DELETE_DATA
      *         (partially installed apps with data directory) will be returned.
@@ -1221,7 +1221,7 @@
      * @see #GET_SERVICES
      * @see #GET_SIGNATURES
      * @see #GET_UNINSTALLED_PACKAGES
-     * 
+     *
      */
     public abstract List<PackageInfo> getInstalledPackages(int flags);
 
@@ -1283,7 +1283,7 @@
      * the device is rebooted before it is written.
      */
     public abstract boolean addPermissionAsync(PermissionInfo info);
-    
+
     /**
      * Removes a permission that was previously added with
      * {@link #addPermission(PermissionInfo)}.  The same ownership rules apply
@@ -1370,7 +1370,7 @@
      * user id is not currently assigned.
      */
     public abstract String getNameForUid(int uid);
-    
+
     /**
      * Return the user id associated with a shared user name. Multiple
      * applications can specify a shared user name in their manifest and thus
@@ -1391,38 +1391,38 @@
      * device. If flag GET_UNINSTALLED_PACKAGES has been set, a list of all
      * applications including those deleted with DONT_DELETE_DATA(partially
      * installed apps with data directory) will be returned.
-     * 
-     * @param flags Additional option flags. Use any combination of 
+     *
+     * @param flags Additional option flags. Use any combination of
      * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES},
      * {link #GET_UNINSTALLED_PACKAGES} to modify the data returned.
      *
      * @return A List of ApplicationInfo objects, one for each application that
      *         is installed on the device.  In the unlikely case of there being
-     *         no installed applications, an empty list is returned. 
+     *         no installed applications, an empty list is returned.
      *         If flag GET_UNINSTALLED_PACKAGES is set, a list of all
      *         applications including those deleted with DONT_DELETE_DATA
      *         (partially installed apps with data directory) will be returned.
-     *         
+     *
      * @see #GET_META_DATA
      * @see #GET_SHARED_LIBRARY_FILES
      * @see #GET_UNINSTALLED_PACKAGES
      */
     public abstract List<ApplicationInfo> getInstalledApplications(int flags);
-    
+
     /**
      * Get a list of shared libraries that are available on the
      * system.
-     * 
+     *
      * @return An array of shared library names that are
      * available on the system, or null if none are installed.
-     * 
+     *
      */
     public abstract String[] getSystemSharedLibraryNames();
 
     /**
      * Get a list of features that are available on the
      * system.
-     * 
+     *
      * @return An array of FeatureInfo classes describing the features
      * that are available on the system, or null if there are none(!!).
      */
@@ -1431,7 +1431,7 @@
     /**
      * Check whether the given feature name is one of the available
      * features as returned by {@link #getSystemAvailableFeatures()}.
-     * 
+     *
      * @return Returns true if the devices supports the feature, else
      * false.
      */
@@ -1448,7 +1448,7 @@
      * that {@link android.content.Context#startActivity(Intent)} and
      * {@link android.content.Intent#resolveActivity(PackageManager)
      * Intent.resolveActivity(PackageManager)} do.</p>
-     * 
+     *
      * @param intent An intent containing all of the desired specification
      *               (action, data, type, category, and/or component).
      * @param flags Additional option flags.  The most important is
@@ -1747,7 +1747,7 @@
      *
      * @return Returns the image of the logo or null if the activity has no
      * logo specified.
-     * 
+     *
      * @throws NameNotFoundException Thrown if the resources for the given
      * activity could not be loaded.
      *
@@ -1768,7 +1768,7 @@
      *
      * @return Returns the image of the logo, or null if the activity has no
      * logo specified.
-     * 
+     *
      * @throws NameNotFoundException Thrown if the resources for application
      * matching the given intent could not be loaded.
      *
@@ -1801,7 +1801,7 @@
      *
      * @return Returns the image of the logo, or null if no application logo
      * has been specified.
-     * 
+     *
      * @throws NameNotFoundException Thrown if the resources for the given
      * application could not be loaded.
      *
@@ -1935,7 +1935,7 @@
      * @see #GET_RECEIVERS
      * @see #GET_SERVICES
      * @see #GET_SIGNATURES
-     * 
+     *
      */
     public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) {
         PackageParser packageParser = new PackageParser(archiveFilePath);
@@ -1952,7 +1952,7 @@
 
     /**
      * @hide
-     * 
+     *
      * Install a package. Since this may take a little while, the result will
      * be posted back to the given observer.  An installation will fail if the calling context
      * lacks the {@link android.Manifest.permission#INSTALL_PACKAGES} permission, if the
@@ -2012,11 +2012,11 @@
     /**
      * Retrieve the package name of the application that installed a package. This identifies
      * which market the package came from.
-     * 
+     *
      * @param packageName The name of the package to query
      */
     public abstract String getInstallerPackageName(String packageName);
-    
+
     /**
      * Attempts to clear the user data directory of an application.
      * Since this may take a little while, the result will
@@ -2071,7 +2071,7 @@
      * of bytes if possible.
      * @param observer call back used to notify when
      * the operation is completed
-     * 
+     *
      * @hide
      */
     public abstract void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer);
@@ -2096,7 +2096,7 @@
      * @param pi IntentSender call back used to
      * notify when the operation is completed.May be null
      * to indicate that no call back is desired.
-     * 
+     *
      * @hide
      */
     public abstract void freeStorage(long freeStorageSize, IntentSender pi);
@@ -2172,7 +2172,7 @@
      * @deprecated This is a protected API that should not have been available
      * to third party applications.  It is the platform's responsibility for
      * assigning preferred activities and this can not be directly modified.
-     * 
+     *
      * Add a new preferred activity mapping to the system.  This will be used
      * to automatically select the given activity component when
      * {@link Context#startActivity(Intent) Context.startActivity()} finds
@@ -2195,7 +2195,7 @@
      * @deprecated This is a protected API that should not have been available
      * to third party applications.  It is the platform's responsibility for
      * assigning preferred activities and this can not be directly modified.
-     * 
+     *
      * Replaces an existing preferred activity mapping to the system, and if that were not present
      * adds a new preferred activity.  This will be used
      * to automatically select the given activity component when
@@ -2304,7 +2304,7 @@
      */
     public abstract void setApplicationEnabledSetting(String packageName,
             int newState, int flags);
-    
+
     /**
      * Return the the enabled setting for an application.  This returns
      * the last value set by
@@ -2345,4 +2345,46 @@
      */
     public abstract void movePackage(
             String packageName, IPackageMoveObserver observer, int flags);
+
+    /**
+     * Creates a user with the specified name and options.
+     *
+     * @param name the user's name
+     * @param flags flags that identify the type of user and other properties.
+     * @see UserInfo
+     *
+     * @return the UserInfo object for the created user, or null if the user could not be created.
+     * @hide
+     */
+    public abstract UserInfo createUser(String name, int flags);
+
+    /**
+     * @return the list of users that were created
+     * @hide
+     */
+    public abstract List<UserInfo> getUsers();
+
+    /**
+     * @param id the ID of the user, where 0 is the primary user.
+     * @hide
+     */
+    public abstract boolean removeUser(int id);
+
+    /**
+     * Updates the user's name.
+     *
+     * @param id the user's id
+     * @param name the new name for the user
+     * @hide
+     */
+    public abstract void updateUserName(int id, String name);
+
+    /**
+     * Changes the user's properties specified by the flags.
+     *
+     * @param id the user's id
+     * @param flags the new flags for the user
+     * @hide
+     */
+    public abstract void updateUserFlags(int id, int flags);
 }
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
new file mode 100644
index 0000000..3704d3a
--- /dev/null
+++ b/core/java/android/content/pm/UserInfo.java
@@ -0,0 +1,106 @@
+/*
+ * 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.content.pm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Per-user information.
+ * @hide
+ */
+public class UserInfo implements Parcelable {
+    /**
+     * Primary user. Only one user can have this flag set. Meaning of this
+     * flag TBD.
+     */
+    public static final int FLAG_PRIMARY = 0x00000001;
+
+    /**
+     * User with administrative privileges. Such a user can create and
+     * delete users.
+     */
+    public static final int FLAG_ADMIN   = 0x00000002;
+
+    /**
+     * Indicates a guest user that may be transient.
+     */
+    public static final int FLAG_GUEST   = 0x00000004;
+
+    public int id;
+    public String name;
+    public int flags;
+
+    public UserInfo(int id, String name, int flags) {
+        this.id = id;
+        this.name = name;
+        this.flags = flags;
+    }
+
+    public boolean isPrimary() {
+        return (flags & FLAG_PRIMARY) == FLAG_PRIMARY;
+    }
+
+    public boolean isAdmin() {
+        return (flags & FLAG_ADMIN) == FLAG_ADMIN;
+    }
+
+    public boolean isGuest() {
+        return (flags & FLAG_GUEST) == FLAG_GUEST;
+    }
+
+    public UserInfo() {
+    }
+
+    public UserInfo(UserInfo orig) {
+        name = orig.name;
+        id = orig.id;
+        flags = orig.flags;
+    }
+
+    @Override
+    public String toString() {
+        return "UserInfo{"
+ + id + ":" + name + ":" + Integer.toHexString(flags) + "}";
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel dest, int parcelableFlags) {
+        dest.writeInt(id);
+        dest.writeString(name);
+        dest.writeInt(flags);
+    }
+
+    public static final Parcelable.Creator<UserInfo> CREATOR
+            = new Parcelable.Creator<UserInfo>() {
+        public UserInfo createFromParcel(Parcel source) {
+            return new UserInfo(source);
+        }
+        public UserInfo[] newArray(int size) {
+            return new UserInfo[size];
+        }
+    };
+
+    private UserInfo(Parcel source) {
+        id = source.readInt();
+        name = source.readString();
+        flags = source.readInt();
+    }
+}
diff --git a/core/java/android/nfc/ApduList.aidl b/core/java/android/nfc/ApduList.aidl
new file mode 100644
index 0000000..f6236b2
--- /dev/null
+++ b/core/java/android/nfc/ApduList.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.nfc;
+
+parcelable ApduList;
\ No newline at end of file
diff --git a/core/java/android/nfc/ApduList.java b/core/java/android/nfc/ApduList.java
new file mode 100644
index 0000000..85b0547
--- /dev/null
+++ b/core/java/android/nfc/ApduList.java
@@ -0,0 +1,68 @@
+package android.nfc;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @hide
+ */
+public class ApduList implements Parcelable {
+
+    private ArrayList<byte[]> commands = new ArrayList<byte[]>();
+
+    public ApduList() {
+    }
+
+    public void add(byte[] command) {
+        commands.add(command);
+    }
+
+    public List<byte[]> get() {
+        return commands;
+    }
+
+    public static final Parcelable.Creator<ApduList> CREATOR =
+        new Parcelable.Creator<ApduList>() {
+        @Override
+        public ApduList createFromParcel(Parcel in) {
+            return new ApduList(in);
+        }
+
+        @Override
+        public ApduList[] newArray(int size) {
+            return new ApduList[size];
+        }
+    };
+
+    private ApduList(Parcel in) {
+        int count = in.readInt();
+
+        for (int i = 0 ; i < count ; i++) {
+
+            int length = in.readInt();
+            byte[] cmd = new byte[length];
+            in.readByteArray(cmd);
+            commands.add(cmd);
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(commands.size());
+
+        for (byte[] cmd : commands) {
+            dest.writeInt(cmd.length);
+            dest.writeByteArray(cmd);
+        }
+    }
+}
+
+
diff --git a/core/java/android/nfc/INfcAdapterExtras.aidl b/core/java/android/nfc/INfcAdapterExtras.aidl
index ab5c1a6..8677a50 100755
--- a/core/java/android/nfc/INfcAdapterExtras.aidl
+++ b/core/java/android/nfc/INfcAdapterExtras.aidl
@@ -16,8 +16,10 @@
 
 package android.nfc;
 
+import android.nfc.ApduList;
 import android.os.Bundle;
 
+
 /**
  * {@hide}
  */
@@ -26,5 +28,7 @@
     Bundle close();
     Bundle transceive(in byte[] data_in);
     int getCardEmulationRoute();
-    void setCardEmulationRoute(int route);    
+    void setCardEmulationRoute(int route);
+    void registerTearDownApdus(String packageName, in ApduList apdu);
+    void unregisterTearDownApdus(String packageName);
 }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 7151ac2..f85df6c 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -101,7 +101,7 @@
      * Defines the UID/GID for the NFC service process.
      * @hide
      */
-    public static final int NFC_UID = 1023;
+    public static final int NFC_UID = 1025;
 
     /**
      * Defines the GID for the group that allows write access to the internal media storage.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ccab8e5..a675618 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3707,6 +3707,13 @@
                 "inet_condition_debounce_down_delay";
 
         /**
+         * URL to open browser on to allow user to manage a prepay account
+         * @hide
+         */
+        public static final String SETUP_PREPAID_DATA_SERVICE_URL =
+                "setup_prepaid_data_service_url";
+
+        /**
          * @hide
          */
         public static final String[] SETTINGS_TO_BACKUP = {
diff --git a/core/java/android/text/CharSequenceIterator.java b/core/java/android/text/CharSequenceIterator.java
index 4946406..4b8ac10 100644
--- a/core/java/android/text/CharSequenceIterator.java
+++ b/core/java/android/text/CharSequenceIterator.java
@@ -16,22 +16,18 @@
 
 package android.text;
 
-import android.util.MathUtils;
-
 import java.text.CharacterIterator;
 
 /** {@hide} */
 public class CharSequenceIterator implements CharacterIterator {
     private final CharSequence mValue;
 
-    private final int mStart;
-    private final int mEnd;
+    private final int mLength;
     private int mIndex;
 
     public CharSequenceIterator(CharSequence value) {
         mValue = value;
-        mStart = 0;
-        mEnd = value.length();
+        mLength = value.length();
         mIndex = 0;
     }
 
@@ -46,7 +42,7 @@
 
     /** {@inheritDoc} */
     public char current() {
-        if (mIndex == mEnd) {
+        if (mIndex == mLength) {
             return DONE;
         }
         return mValue.charAt(mIndex);
@@ -54,12 +50,12 @@
 
     /** {@inheritDoc} */
     public int getBeginIndex() {
-        return mStart;
+        return 0;
     }
 
     /** {@inheritDoc} */
     public int getEndIndex() {
-        return mEnd;
+        return mLength;
     }
 
     /** {@inheritDoc} */
@@ -69,27 +65,36 @@
 
     /** {@inheritDoc} */
     public char first() {
-        return setIndex(mStart);
+        return setIndex(0);
     }
 
     /** {@inheritDoc} */
     public char last() {
-        return setIndex(mEnd - 1);
+        return setIndex(mLength - 1);
     }
 
     /** {@inheritDoc} */
     public char next() {
+        if (mIndex == mLength) {
+            return DONE;
+        }
         return setIndex(mIndex + 1);
     }
 
     /** {@inheritDoc} */
     public char previous() {
+        if (mIndex == 0) {
+            return DONE;
+        }
         return setIndex(mIndex - 1);
     }
 
     /** {@inheritDoc} */
     public char setIndex(int index) {
-        mIndex = MathUtils.constrain(index, mStart, mEnd);
+        if ((index < 0) || (index > mLength)) {
+            throw new IllegalArgumentException("Valid range is [" + 0 + "..." + mLength + "]");
+        }
+        mIndex = index;
         return current();
     }
 }
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 80c0106..b25ba8d 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -390,7 +390,7 @@
         }
 
         private boolean isValidOffset(int offset) {
-            return offset >= 0 && offset < mCurrent.length();
+            return offset >= 0 && offset <= mCurrent.length();
         }
 
         private boolean isLetterOrDigit(int offset) {
@@ -404,7 +404,7 @@
         /** {@inheritDoc} */
         public int preceding(int offset) {
             // always round cursor index into valid string index
-            offset = MathUtils.constrain(offset, 0, mCurrent.length() - 1);
+            offset = MathUtils.constrain(offset, 0, mCurrent.length());
 
             do {
                 offset = mIterator.preceding(offset);
@@ -417,7 +417,7 @@
         /** {@inheritDoc} */
         public int following(int offset) {
             // always round cursor index into valid string index
-            offset = MathUtils.constrain(offset, 0, mCurrent.length() - 1);
+            offset = MathUtils.constrain(offset, 0, mCurrent.length());
 
             do {
                 offset = mIterator.following(offset);
diff --git a/core/java/com/android/internal/util/HierarchicalStateMachine.java b/core/java/com/android/internal/util/HierarchicalStateMachine.java
index f43f459..f6aa184 100644
--- a/core/java/com/android/internal/util/HierarchicalStateMachine.java
+++ b/core/java/com/android/internal/util/HierarchicalStateMachine.java
@@ -24,6 +24,7 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Vector;
 
 /**
  * {@hide}
@@ -433,6 +434,180 @@
      */
     public static final boolean NOT_HANDLED = false;
 
+    /**
+     * {@hide}
+     *
+     * The information maintained for a processed message.
+     */
+    public static class ProcessedMessageInfo {
+        private int what;
+        private HierarchicalState state;
+        private HierarchicalState orgState;
+
+        /**
+         * Constructor
+         * @param message
+         * @param state that handled the message
+         * @param orgState is the first state the received the message but
+         * did not processes the message.
+         */
+        ProcessedMessageInfo(Message message, HierarchicalState state, HierarchicalState orgState) {
+            update(message, state, orgState);
+        }
+
+        /**
+         * Update the information in the record.
+         * @param state that handled the message
+         * @param orgState is the first state the received the message but
+         * did not processes the message.
+         */
+        public void update(Message message, HierarchicalState state, HierarchicalState orgState) {
+            this.what = message.what;
+            this.state = state;
+            this.orgState = orgState;
+        }
+
+        /**
+         * @return the command that was executing
+         */
+        public int getWhat() {
+            return what;
+        }
+
+        /**
+         * @return the state that handled this message
+         */
+        public HierarchicalState getState() {
+            return state;
+        }
+
+        /**
+         * @return the original state that received the message.
+         */
+        public HierarchicalState getOriginalState() {
+            return orgState;
+        }
+
+        /**
+         * @return as string
+         */
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("what=");
+            sb.append(what);
+            sb.append(" state=");
+            sb.append(cn(state));
+            sb.append(" orgState=");
+            sb.append(cn(orgState));
+            return sb.toString();
+        }
+
+        /**
+         * @return an objects class name
+         */
+        private String cn(Object n) {
+            if (n == null) {
+                return "null";
+            } else {
+                String name = n.getClass().getName();
+                int lastDollar = name.lastIndexOf('$');
+                return name.substring(lastDollar + 1);
+            }
+        }
+    }
+
+    /**
+     * A list of messages recently processed by the state machine.
+     *
+     * The class maintains a list of messages that have been most
+     * recently processed. The list is finite and may be set in the
+     * constructor or by calling setSize. The public interface also
+     * includes size which returns the number of recent messages,
+     * count which is the number of message processed since the
+     * the last setSize, get which returns a processed message and
+     * add which adds a processed messaged.
+     */
+    private static class ProcessedMessages {
+
+        private static final int DEFAULT_SIZE = 20;
+
+        private Vector<ProcessedMessageInfo> mMessages = new Vector<ProcessedMessageInfo>();
+        private int mMaxSize = DEFAULT_SIZE;
+        private int mOldestIndex = 0;
+        private int mCount = 0;
+
+        /**
+         * Constructor
+         */
+        ProcessedMessages() {
+        }
+
+        /**
+         * Set size of messages to maintain and clears all current messages.
+         *
+         * @param maxSize number of messages to maintain at anyone time.
+        */
+        void setSize(int maxSize) {
+            mMaxSize = maxSize;
+            mCount = 0;
+            mMessages.clear();
+        }
+
+        /**
+         * @return the number of recent messages.
+         */
+        int size() {
+            return mMessages.size();
+        }
+
+        /**
+         * @return the total number of messages processed since size was set.
+         */
+        int count() {
+            return mCount;
+        }
+
+        /**
+         * @return the information on a particular record. 0 is the oldest
+         * record and size()-1 is the newest record. If the index is to
+         * large null is returned.
+         */
+        ProcessedMessageInfo get(int index) {
+            int nextIndex = mOldestIndex + index;
+            if (nextIndex >= mMaxSize) {
+                nextIndex -= mMaxSize;
+            }
+            if (nextIndex >= size()) {
+                return null;
+            } else {
+                return mMessages.get(nextIndex);
+            }
+        }
+
+        /**
+         * Add a processed message.
+         *
+         * @param message
+         * @param state that handled the message
+         * @param orgState is the first state the received the message but
+         * did not processes the message.
+         */
+        void add(Message message, HierarchicalState state, HierarchicalState orgState) {
+            mCount += 1;
+            if (mMessages.size() < mMaxSize) {
+                mMessages.add(new ProcessedMessageInfo(message, state, orgState));
+            } else {
+                ProcessedMessageInfo pmi = mMessages.get(mOldestIndex);
+                mOldestIndex += 1;
+                if (mOldestIndex >= mMaxSize) {
+                    mOldestIndex = 0;
+                }
+                pmi.update(message, state, orgState);
+            }
+        }
+    }
+
     private static class HsmHandler extends Handler {
 
         /** The debug flag */
@@ -441,9 +616,6 @@
         /** The quit object */
         private static final Object mQuitObj = new Object();
 
-        /** The initialization message */
-        private static final Message mInitMsg = null;
-
         /** The current message */
         private Message mMsg;
 
@@ -615,8 +787,9 @@
                      */
                     mHsm.quitting();
                     if (mHsm.mHsmThread != null) {
-                        // If we made the thread then quit looper
+                        // If we made the thread then quit looper which stops the thread.
                         getLooper().quit();
+                        mHsm.mHsmThread = null;
                     }
                 } else if (destState == mHaltingState) {
                     /**
@@ -963,8 +1136,8 @@
             return mProcessedMessages.count();
         }
 
-        /** @see HierarchicalStateMachine#getProcessedMessage(int) */
-        private final ProcessedMessages.Info getProcessedMessage(int index) {
+        /** @see HierarchicalStateMachine#getProcessedMessageInfo(int) */
+        private final ProcessedMessageInfo getProcessedMessageInfo(int index) {
             return mProcessedMessages.get(index);
         }
 
@@ -1090,9 +1263,7 @@
      * @param msg that couldn't be handled.
      */
     protected void unhandledMessage(Message msg) {
-        if (false) {
-            Log.e(TAG, mName + " - unhandledMessage: msg.what=" + msg.what);
-        }
+        if (mHsmHandler.mDbg) Log.e(TAG, mName + " - unhandledMessage: msg.what=" + msg.what);
     }
 
     /**
@@ -1103,16 +1274,18 @@
     }
 
     /**
-     * Called after the message that called transitionToHalting
-     * is called and should be overridden by StateMachine's that
-     * call transitionToHalting.
+     * This will be called once after handling a message that called
+     * transitionToHalting. All subsequent messages will invoke
+     * {@link HierarchicalStateMachine#haltedProcessMessage(Message)}
      */
     protected void halting() {
     }
 
     /**
-     * Called after the quitting message was NOT handled and
-     * just before the quit actually occurs.
+     * This will be called once after a quit message that was NOT handled by
+     * the derived HSM. The HSM will stop and any subsequent messages will be
+     * ignored. In addition, if this HSM created the thread, the thread will
+     * be stopped after this method returns.
      */
     protected void quitting() {
     }
@@ -1148,10 +1321,10 @@
     }
 
     /**
-     * @return a processed message
+     * @return a processed message information
      */
-    public final ProcessedMessages.Info getProcessedMessage(int index) {
-        return mHsmHandler.getProcessedMessage(index);
+    public final ProcessedMessageInfo getProcessedMessageInfo(int index) {
+        return mHsmHandler.getProcessedMessageInfo(index);
     }
 
     /**
diff --git a/core/java/com/android/internal/util/ProcessedMessages.java b/core/java/com/android/internal/util/ProcessedMessages.java
deleted file mode 100644
index 244474e..0000000
--- a/core/java/com/android/internal/util/ProcessedMessages.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/**
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.util;
-
-import android.os.Message;
-
-import java.util.Vector;
-
-/**
- * {@hide}
- *
- * A list of messages recently processed by the state machine.
- *
- * The class maintains a list of messages that have been most
- * recently processed. The list is finite and may be set in the
- * constructor or by calling setSize. The public interface also
- * includes size which returns the number of recent messages,
- * count which is the number of message processed since the
- * the last setSize, get which returns a processed message and
- * add which adds a processed messaged.
- */
-public class ProcessedMessages {
-
-    public static final int DEFAULT_SIZE = 20;
-
-    /**
-     * The information maintained for a processed message.
-     */
-    public class Info {
-        private int what;
-        private HierarchicalState state;
-        private HierarchicalState orgState;
-
-        /**
-         * Constructor
-         * @param message
-         * @param state that handled the message
-         * @param orgState is the first state the received the message but
-         * did not processes the message.
-         */
-        Info(Message message, HierarchicalState state, HierarchicalState orgState) {
-            update(message, state, orgState);
-        }
-
-        /**
-         * Update the information in the record.
-         * @param state that handled the message
-         * @param orgState is the first state the received the message but
-         * did not processes the message.
-         */
-        public void update(Message message, HierarchicalState state, HierarchicalState orgState) {
-            this.what = message.what;
-            this.state = state;
-            this.orgState = orgState;
-        }
-
-        /**
-         * @return the command that was executing
-         */
-        public int getWhat() {
-            return what;
-        }
-
-        /**
-         * @return the state that handled this message
-         */
-        public HierarchicalState getState() {
-            return state;
-        }
-
-        /**
-         * @return the original state that received the message.
-         */
-        public HierarchicalState getOriginalState() {
-            return orgState;
-        }
-
-        /**
-         * @return as string
-         */
-        public String toString() {
-            StringBuilder sb = new StringBuilder();
-            sb.append("what=");
-            sb.append(what);
-            sb.append(" state=");
-            sb.append(cn(state));
-            sb.append(" orgState=");
-            sb.append(cn(orgState));
-            return sb.toString();
-        }
-
-        /**
-         * @return an objects class name
-         */
-        private String cn(Object n) {
-            if (n == null) {
-                return "null";
-            } else {
-                String name = n.getClass().getName();
-                int lastDollar = name.lastIndexOf('$');
-                return name.substring(lastDollar + 1);
-            }
-        }
-    }
-
-    private Vector<Info> mMessages = new Vector<Info>();
-    private int mMaxSize = DEFAULT_SIZE;
-    private int mOldestIndex = 0;
-    private int mCount = 0;
-
-    /**
-     * Constructor
-     */
-    ProcessedMessages() {
-    }
-
-    ProcessedMessages(int maxSize) {
-        setSize(maxSize);
-    }
-
-    /**
-     * Set size of messages to maintain and clears all current messages.
-     *
-     * @param maxSize number of messages to maintain at anyone time.
-    */
-    void setSize(int maxSize) {
-        mMaxSize = maxSize;
-        mCount = 0;
-        mMessages.clear();
-    }
-
-    /**
-     * @return the number of recent messages.
-     */
-    int size() {
-        return mMessages.size();
-    }
-
-    /**
-     * @return the total number of messages processed since size was set.
-     */
-    int count() {
-        return mCount;
-    }
-
-    /**
-     * @return the information on a particular record. 0 is the oldest
-     * record and size()-1 is the newest record. If the index is to
-     * large null is returned.
-     */
-    Info get(int index) {
-        int nextIndex = mOldestIndex + index;
-        if (nextIndex >= mMaxSize) {
-            nextIndex -= mMaxSize;
-        }
-        if (nextIndex >= size()) {
-            return null;
-        } else {
-            return mMessages.get(nextIndex);
-        }
-    }
-
-    /**
-     * Add a processed message.
-     *
-     * @param message
-     * @param state that handled the message
-     * @param orgState is the first state the received the message but
-     * did not processes the message.
-     */
-    void add(Message message, HierarchicalState state, HierarchicalState orgState) {
-        mCount += 1;
-        if (mMessages.size() < mMaxSize) {
-            mMessages.add(new Info(message, state, orgState));
-        } else {
-            Info info = mMessages.get(mOldestIndex);
-            mOldestIndex += 1;
-            if (mOldestIndex >= mMaxSize) {
-                mOldestIndex = 0;
-            }
-            info.update(message, state, orgState);
-        }
-    }
-}
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 1034fbd..258ffa5 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -12,6 +12,7 @@
 #include "CreateJavaOutputStreamAdaptor.h"
 #include "AutoDecodeCancel.h"
 #include "Utils.h"
+#include "JNIHelp.h"
 
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/Asset.h>
@@ -20,7 +21,6 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 
-jclass gOptions_class;
 jfieldID gOptions_justBoundsFieldID;
 jfieldID gOptions_sampleSizeFieldID;
 jfieldID gOptions_configFieldID;
@@ -34,12 +34,8 @@
 jfieldID gOptions_mimeFieldID;
 jfieldID gOptions_mCancelID;
 jfieldID gOptions_bitmapFieldID;
-jclass gBitmap_class;
 jfieldID gBitmap_nativeBitmapFieldID;
 
-static jclass gFileDescriptor_class;
-static jfieldID gFileDescriptor_descriptor;
-
 #if 0
     #define TRACE_BITMAP(code)  code
 #else
@@ -66,7 +62,7 @@
         { SkImageDecoder::kPNG_Format,  "image/png" },
         { SkImageDecoder::kWBMP_Format, "image/vnd.wap.wbmp" }
     };
-    
+
     const char* cstr = NULL;
     for (size_t i = 0; i < SK_ARRAY_COUNT(gMimeTypes); i++) {
         if (gMimeTypes[i].fFormat == format) {
@@ -127,7 +123,7 @@
                         (allowPurgeable && optionsPurgeable(env, options));
     bool preferQualityOverSpeed = false;
     jobject javaBitmap = NULL;
-    
+
     if (NULL != options) {
         sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
         if (optionsJustBounds(env, options)) {
@@ -137,7 +133,7 @@
         env->SetIntField(options, gOptions_widthFieldID, -1);
         env->SetIntField(options, gOptions_heightFieldID, -1);
         env->SetObjectField(options, gOptions_mimeFieldID, 0);
-        
+
         jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
         prefConfig = GraphicsJNI::getNativeBitmapConfig(env, jconfig);
         isMutable = env->GetBooleanField(options, gOptions_mutableFieldID);
@@ -151,7 +147,7 @@
     if (NULL == decoder) {
         return nullObjectReturn("SkImageDecoder::Factory returned null");
     }
-    
+
     decoder->setSampleSize(sampleSize);
     decoder->setDitherImage(doDither);
     decoder->setPreferQualityOverSpeed(preferQualityOverSpeed);
@@ -298,8 +294,7 @@
                                           jobject bitmapFactoryOptions) {
     NPE_CHECK_RETURN_ZERO(env, fileDescriptor);
 
-    jint descriptor = env->GetIntField(fileDescriptor,
-                                       gFileDescriptor_descriptor);
+    jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);
 
     bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions);
     bool isShareable = optionsShareable(env, bitmapFactoryOptions);
@@ -424,7 +419,7 @@
         }
 
         for (int i = 0; i < chunk->numYDivs; i++) {
-            chunk->yDivs[i] = int(chunk->yDivs[i] * scale + 0.5f);            
+            chunk->yDivs[i] = int(chunk->yDivs[i] * scale + 0.5f);
             if (i > 0 && chunk->yDivs[i] == chunk->yDivs[i - 1]) {
                 chunk->yDivs[i]++;
             }
@@ -460,7 +455,7 @@
 }
 
 static jboolean nativeIsSeekable(JNIEnv* env, jobject, jobject fileDescriptor) {
-    jint descriptor = env->GetIntField(fileDescriptor, gFileDescriptor_descriptor);
+    jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);
     return ::lseek64(descriptor, 0, SEEK_CUR) != -1 ? JNI_TRUE : JNI_FALSE;
 }
 
@@ -504,12 +499,6 @@
     {   "requestCancel", "()V", (void*)nativeRequestCancel }
 };
 
-static jclass make_globalref(JNIEnv* env, const char classname[]) {
-    jclass c = env->FindClass(classname);
-    SkASSERT(c);
-    return (jclass)env->NewGlobalRef(c);
-}
-
 static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
                                 const char fieldname[], const char type[]) {
     jfieldID id = env->GetFieldID(clazz, fieldname, type);
@@ -517,35 +506,29 @@
     return id;
 }
 
-#define kClassPathName  "android/graphics/BitmapFactory"
-
-#define RETURN_ERR_IF_NULL(value) \
-    do { if (!(value)) { assert(0); return -1; } } while (false)
-
-int register_android_graphics_BitmapFactory(JNIEnv* env);
 int register_android_graphics_BitmapFactory(JNIEnv* env) {
-    gOptions_class = make_globalref(env, "android/graphics/BitmapFactory$Options");
-    gOptions_bitmapFieldID = getFieldIDCheck(env, gOptions_class, "inBitmap",
+    jclass options_class = env->FindClass("android/graphics/BitmapFactory$Options");
+    SkASSERT(options_class);
+    gOptions_bitmapFieldID = getFieldIDCheck(env, options_class, "inBitmap",
         "Landroid/graphics/Bitmap;");
-    gOptions_justBoundsFieldID = getFieldIDCheck(env, gOptions_class, "inJustDecodeBounds", "Z");
-    gOptions_sampleSizeFieldID = getFieldIDCheck(env, gOptions_class, "inSampleSize", "I");
-    gOptions_configFieldID = getFieldIDCheck(env, gOptions_class, "inPreferredConfig",
+    gOptions_justBoundsFieldID = getFieldIDCheck(env, options_class, "inJustDecodeBounds", "Z");
+    gOptions_sampleSizeFieldID = getFieldIDCheck(env, options_class, "inSampleSize", "I");
+    gOptions_configFieldID = getFieldIDCheck(env, options_class, "inPreferredConfig",
             "Landroid/graphics/Bitmap$Config;");
-    gOptions_mutableFieldID = getFieldIDCheck(env, gOptions_class, "inMutable", "Z");
-    gOptions_ditherFieldID = getFieldIDCheck(env, gOptions_class, "inDither", "Z");
-    gOptions_purgeableFieldID = getFieldIDCheck(env, gOptions_class, "inPurgeable", "Z");
-    gOptions_shareableFieldID = getFieldIDCheck(env, gOptions_class, "inInputShareable", "Z");
-    gOptions_preferQualityOverSpeedFieldID = getFieldIDCheck(env, gOptions_class,
+    gOptions_mutableFieldID = getFieldIDCheck(env, options_class, "inMutable", "Z");
+    gOptions_ditherFieldID = getFieldIDCheck(env, options_class, "inDither", "Z");
+    gOptions_purgeableFieldID = getFieldIDCheck(env, options_class, "inPurgeable", "Z");
+    gOptions_shareableFieldID = getFieldIDCheck(env, options_class, "inInputShareable", "Z");
+    gOptions_preferQualityOverSpeedFieldID = getFieldIDCheck(env, options_class,
             "inPreferQualityOverSpeed", "Z");
-    gOptions_widthFieldID = getFieldIDCheck(env, gOptions_class, "outWidth", "I");
-    gOptions_heightFieldID = getFieldIDCheck(env, gOptions_class, "outHeight", "I");
-    gOptions_mimeFieldID = getFieldIDCheck(env, gOptions_class, "outMimeType", "Ljava/lang/String;");
-    gOptions_mCancelID = getFieldIDCheck(env, gOptions_class, "mCancel", "Z");
+    gOptions_widthFieldID = getFieldIDCheck(env, options_class, "outWidth", "I");
+    gOptions_heightFieldID = getFieldIDCheck(env, options_class, "outHeight", "I");
+    gOptions_mimeFieldID = getFieldIDCheck(env, options_class, "outMimeType", "Ljava/lang/String;");
+    gOptions_mCancelID = getFieldIDCheck(env, options_class, "mCancel", "Z");
 
-    gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
-    gBitmap_nativeBitmapFieldID = getFieldIDCheck(env, gBitmap_class, "mNativeBitmap", "I");
-    gFileDescriptor_class = make_globalref(env, "java/io/FileDescriptor");
-    gFileDescriptor_descriptor = getFieldIDCheck(env, gFileDescriptor_class, "descriptor", "I");
+    jclass bitmap_class = env->FindClass("android/graphics/Bitmap");
+    SkASSERT(bitmap_class);
+    gBitmap_nativeBitmapFieldID = getFieldIDCheck(env, bitmap_class, "mNativeBitmap", "I");
 
     int ret = AndroidRuntime::registerNativeMethods(env,
                                     "android/graphics/BitmapFactory$Options",
@@ -554,6 +537,6 @@
     if (ret) {
         return ret;
     }
-    return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
+    return android::AndroidRuntime::registerNativeMethods(env, "android/graphics/BitmapFactory",
                                          gMethods, SK_ARRAY_COUNT(gMethods));
 }
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index ee3e209..d437929 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -28,6 +28,7 @@
 #include "SkBitmapRegionDecoder.h"
 #include "CreateJavaOutputStreamAdaptor.h"
 #include "Utils.h"
+#include "JNIHelp.h"
 
 #include <android_runtime/AndroidRuntime.h>
 #include "android_util_Binder.h"
@@ -39,9 +40,6 @@
 #include <utils/Asset.h>
 #include <sys/stat.h>
 
-static jclass gFileDescriptor_class;
-static jfieldID gFileDescriptor_descriptor;
-
 #if 0
     #define TRACE_BITMAP(code)  code
 #else
@@ -111,8 +109,7 @@
                                           jobject fileDescriptor, jboolean isShareable) {
     NPE_CHECK_RETURN_ZERO(env, fileDescriptor);
 
-    jint descriptor = env->GetIntField(fileDescriptor,
-                                       gFileDescriptor_descriptor);
+    jint descriptor = jniGetFDFromFileDescriptor(env, fileDescriptor);
     SkStream *stream = NULL;
     struct stat fdStat;
     int newFD;
@@ -300,25 +297,8 @@
 
 #define kClassPathName  "android/graphics/BitmapRegionDecoder"
 
-static jclass make_globalref(JNIEnv* env, const char classname[]) {
-    jclass c = env->FindClass(classname);
-    SkASSERT(c);
-    return (jclass)env->NewGlobalRef(c);
-}
-
-static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
-                                const char fieldname[], const char type[]) {
-    jfieldID id = env->GetFieldID(clazz, fieldname, type);
-    SkASSERT(id);
-    return id;
-}
-
-int register_android_graphics_BitmapRegionDecoder(JNIEnv* env);
 int register_android_graphics_BitmapRegionDecoder(JNIEnv* env)
 {
-
-    gFileDescriptor_class = make_globalref(env, "java/io/FileDescriptor");
-    gFileDescriptor_descriptor = getFieldIDCheck(env, gFileDescriptor_class, "descriptor", "I");
     return android::AndroidRuntime::registerNativeMethods(env, kClassPathName,
             gBitmapRegionDecoderMethods, SK_ARRAY_COUNT(gBitmapRegionDecoderMethods));
 }
diff --git a/core/jni/android_backup_BackupDataInput.cpp b/core/jni/android_backup_BackupDataInput.cpp
index b03dd16..c174a41 100644
--- a/core/jni/android_backup_BackupDataInput.cpp
+++ b/core/jni/android_backup_BackupDataInput.cpp
@@ -25,9 +25,6 @@
 namespace android
 {
 
-// java.io.FileDescriptor
-static jfieldID s_descriptorField = 0;
-
 // android.app.backup.BackupDataInput$EntityHeader
 static jfieldID s_keyField = 0;
 static jfieldID s_dataSizeField = 0;
@@ -35,9 +32,7 @@
 static int
 ctor_native(JNIEnv* env, jobject clazz, jobject fileDescriptor)
 {
-    int err;
-
-    int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     if (fd == -1) {
         return NULL;
     }
@@ -140,15 +135,7 @@
 {
     //LOGD("register_android_backup_BackupDataInput");
 
-    jclass clazz;
-
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(s_descriptorField == NULL,
-            "Unable to find descriptor field in java.io.FileDescriptor");
-
-    clazz = env->FindClass("android/app/backup/BackupDataInput$EntityHeader");
+    jclass clazz = env->FindClass("android/app/backup/BackupDataInput$EntityHeader");
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.app.backup.BackupDataInput.EntityHeader");
     s_keyField = env->GetFieldID(clazz, "key", "Ljava/lang/String;");
     LOG_FATAL_IF(s_keyField == NULL,
diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp
index b895d11..144a10c 100644
--- a/core/jni/android_backup_BackupDataOutput.cpp
+++ b/core/jni/android_backup_BackupDataOutput.cpp
@@ -25,14 +25,10 @@
 namespace android
 {
 
-static jfieldID s_descriptorField = 0;
-
 static int
 ctor_native(JNIEnv* env, jobject clazz, jobject fileDescriptor)
 {
-    int err;
-
-    int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     if (fd == -1) {
         return NULL;
     }
@@ -112,15 +108,6 @@
 int register_android_backup_BackupDataOutput(JNIEnv* env)
 {
     //LOGD("register_android_backup_BackupDataOutput");
-
-    jclass clazz;
-
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(s_descriptorField == NULL,
-            "Unable to find descriptor field in java.io.FileDescriptor");
-
     return AndroidRuntime::registerNativeMethods(env, "android/app/backup/BackupDataOutput",
             g_methods, NELEM(g_methods));
 }
diff --git a/core/jni/android_backup_BackupHelperDispatcher.cpp b/core/jni/android_backup_BackupHelperDispatcher.cpp
index 26e7d66..49f1cd4 100644
--- a/core/jni/android_backup_BackupHelperDispatcher.cpp
+++ b/core/jni/android_backup_BackupHelperDispatcher.cpp
@@ -37,8 +37,6 @@
     int nameLength; // not including the NULL terminator, which is not written to the file
 };
 
-// java.io.FileDescriptor
-static jfieldID s_descriptorField = 0;
 static jfieldID s_chunkSizeField = 0;
 static jfieldID s_keyPrefixField = 0;
 
@@ -46,12 +44,11 @@
 readHeader_native(JNIEnv* env, jobject clazz, jobject headerObj, jobject fdObj)
 {
     chunk_header_v1 flattenedHeader;
-    int fd;
     ssize_t amt;
     String8 keyPrefix;
     char* buf;
 
-    fd = env->GetIntField(fdObj, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fdObj);
 
     amt = read(fd, &flattenedHeader.headerSize, sizeof(flattenedHeader.headerSize));
     if (amt != sizeof(flattenedHeader.headerSize)) {
@@ -128,9 +125,7 @@
 static int
 skipChunk_native(JNIEnv* env, jobject clazz, jobject fdObj, jint bytesToSkip)
 {
-    int fd;
-
-    fd = env->GetIntField(fdObj, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fdObj);
 
     lseek(fd, bytesToSkip, SEEK_CUR);
 
@@ -152,9 +147,8 @@
     int nameLength;
     int namePadding;
     int headerSize;
-    int fd;
 
-    fd = env->GetIntField(fdObj, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fdObj);
 
     nameObj = (jstring)env->GetObjectField(headerObj, s_keyPrefixField);
 
@@ -166,7 +160,7 @@
     pos = lseek(fd, 0, SEEK_CUR);
 
     lseek(fd, headerSize, SEEK_CUR);
-    
+
     return pos;
 }
 
@@ -175,13 +169,12 @@
 {
     int err;
     chunk_header_v1 header;
-    int fd;
     int namePadding;
     int prevPos;
     jstring nameObj;
     const char* buf;
 
-    fd = env->GetIntField(fdObj, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fdObj);
     prevPos = lseek(fd, 0, SEEK_CUR);
 
     nameObj = (jstring)env->GetObjectField(headerObj, s_keyPrefixField);
@@ -234,15 +227,7 @@
 
 int register_android_backup_BackupHelperDispatcher(JNIEnv* env)
 {
-    jclass clazz;
-
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(s_descriptorField == NULL,
-            "Unable to find descriptor field in java.io.FileDescriptor");
-    
-    clazz = env->FindClass("android/app/backup/BackupHelperDispatcher$Header");
+    jclass clazz = env->FindClass("android/app/backup/BackupHelperDispatcher$Header");
     LOG_FATAL_IF(clazz == NULL,
             "Unable to find class android.app.backup.BackupHelperDispatcher.Header");
     s_chunkSizeField = env->GetFieldID(clazz, "chunkSize", "I");
@@ -251,7 +236,7 @@
     s_keyPrefixField = env->GetFieldID(clazz, "keyPrefix", "Ljava/lang/String;");
     LOG_FATAL_IF(s_keyPrefixField == NULL,
             "Unable to find keyPrefix field in android.app.backup.BackupHelperDispatcher.Header");
-    
+
     return AndroidRuntime::registerNativeMethods(env, "android/app/backup/BackupHelperDispatcher",
             g_methods, NELEM(g_methods));
 }
diff --git a/core/jni/android_backup_FileBackupHelperBase.cpp b/core/jni/android_backup_FileBackupHelperBase.cpp
index 0137a06..0dfd8db 100644
--- a/core/jni/android_backup_FileBackupHelperBase.cpp
+++ b/core/jni/android_backup_FileBackupHelperBase.cpp
@@ -25,9 +25,6 @@
 namespace android
 {
 
-// java.io.FileDescriptor
-static jfieldID s_descriptorField = 0;
-
 static int
 ctor(JNIEnv* env, jobject clazz)
 {
@@ -47,8 +44,8 @@
     int err;
 
     // all parameters have already been checked against null
-    int oldStateFD = oldState != NULL ? env->GetIntField(oldState, s_descriptorField) : -1;
-    int newStateFD = env->GetIntField(newState, s_descriptorField);
+    int oldStateFD = oldState != NULL ? jniGetFDFromFileDescriptor(env, oldState) : -1;
+    int newStateFD = jniGetFDFromFileDescriptor(env, newState);
     BackupDataWriter* dataStream = (BackupDataWriter*)data;
 
     const int fileCount = env->GetArrayLength(files);
@@ -102,7 +99,7 @@
     int err;
 
     RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
-    int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
 
     err = restore->WriteSnapshot(fd);
 
@@ -121,14 +118,6 @@
 
 int register_android_backup_FileBackupHelperBase(JNIEnv* env)
 {
-    jclass clazz;
-
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(s_descriptorField == NULL,
-            "Unable to find descriptor field in java.io.FileDescriptor");
-    
     return AndroidRuntime::registerNativeMethods(env, "android/app/backup/FileBackupHelperBase",
             g_methods, NELEM(g_methods));
 }
diff --git a/core/jni/android_database_SQLiteStatement.cpp b/core/jni/android_database_SQLiteStatement.cpp
index 97e0483..05ffbb1 100644
--- a/core/jni/android_database_SQLiteStatement.cpp
+++ b/core/jni/android_database_SQLiteStatement.cpp
@@ -143,7 +143,7 @@
 static jobject createParcelFileDescriptor(JNIEnv * env, int fd)
 {
     // Create FileDescriptor object
-    jobject fileDesc = newFileDescriptor(env, fd);
+    jobject fileDesc = jniCreateFileDescriptor(env, fd);
     if (fileDesc == NULL) {
         // FileDescriptor constructor has thrown an exception
         close(fd);
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
index e259514..4d73bf3 100644
--- a/core/jni/android_hardware_UsbDeviceConnection.cpp
+++ b/core/jni/android_hardware_UsbDeviceConnection.cpp
@@ -42,7 +42,7 @@
 android_hardware_UsbDeviceConnection_open(JNIEnv *env, jobject thiz, jstring deviceName,
         jobject fileDescriptor)
 {
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     // duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy
     fd = dup(fd);
     if (fd < 0)
diff --git a/core/jni/android_media_JetPlayer.cpp b/core/jni/android_media_JetPlayer.cpp
index a7ffff4..e1240692 100644
--- a/core/jni/android_media_JetPlayer.cpp
+++ b/core/jni/android_media_JetPlayer.cpp
@@ -175,7 +175,7 @@
     lpJet->setEventCallback(jetPlayerEventCallback);
 
     LOGV("android_media_JetPlayer_openFileDescr(): trying to load JET file through its fd" );
-    EAS_RESULT result = lpJet->loadFromFD(getParcelFileDescriptorFD(env, fileDescriptor),
+    EAS_RESULT result = lpJet->loadFromFD(jniGetFDFromFileDescriptor(env, fileDescriptor),
         (long long)offset, (long long)length); // cast params to types used by EAS_FILE
 
     if(result==EAS_SUCCESS) {
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index 2685d75..6c29d6c 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -2,21 +2,23 @@
 **
 ** Copyright 2009, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -41,10 +43,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -55,7 +53,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -76,26 +74,6 @@
         _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
 }
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -116,13 +94,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -141,7 +119,8 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
@@ -154,7 +133,6 @@
 }
 
 // --------------------------------------------------------------------------
-
 /* void glActiveTexture ( GLenum texture ) */
 static void
 android_glActiveTexture__I
@@ -431,16 +409,16 @@
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
-        _env->ThrowNew(IAEClass, "textures == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     textures_base = (GLuint *)
@@ -469,7 +447,7 @@
 
     textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glDeleteTextures(
@@ -560,7 +538,7 @@
 
     indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining);
     if (_remaining < count) {
-        _env->ThrowNew(AIOOBEClass, "remaining() < count");
+        jniThrowException(_env, "java/lang/ArrayIndexOutOfBoundsException", "remaining() < count");
         goto exit;
     }
     glDrawElements(
@@ -627,11 +605,11 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -661,7 +639,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -715,7 +693,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glFogfv(
@@ -748,11 +726,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -782,7 +760,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -836,7 +814,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glFogxv(
@@ -898,18 +876,18 @@
 
     if (!textures_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "textures == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     textures_base = (GLuint *)
@@ -940,7 +918,7 @@
     textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glGenTextures(
@@ -974,12 +952,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1316,7 +1294,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLint *)
@@ -1678,7 +1656,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetIntegerv(
@@ -1692,16 +1670,10 @@
     }
 }
 
-#include <string.h>
-
 /* const GLubyte * glGetString ( GLenum name ) */
-static
-jstring
-android_glGetString
-  (JNIEnv *_env, jobject _this, jint name) {
-    const char * chars = (const char *)glGetString((GLenum)name);
-    jstring output = _env->NewStringUTF(chars);
-    return output;
+static jstring android_glGetString(JNIEnv* _env, jobject, jint name) {
+    const char* chars = (const char*) glGetString((GLenum) name);
+    return _env->NewStringUTF(chars);
 }
 /* void glHint ( GLenum target, GLenum mode ) */
 static void
@@ -1732,11 +1704,11 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1757,7 +1729,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1802,7 +1774,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glLightModelfv(
@@ -1835,11 +1807,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1860,7 +1832,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1905,7 +1877,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glLightModelxv(
@@ -1939,11 +1911,11 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1990,7 +1962,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2062,7 +2034,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glLightfv(
@@ -2097,11 +2069,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2148,7 +2120,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2220,7 +2192,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glLightxv(
@@ -2269,11 +2241,11 @@
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        _env->ThrowNew(IAEClass, "m == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2318,11 +2290,11 @@
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        _env->ThrowNew(IAEClass, "m == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2387,11 +2359,11 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2424,7 +2396,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2482,7 +2454,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glMaterialfv(
@@ -2517,11 +2489,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2554,7 +2526,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2612,7 +2584,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glMaterialxv(
@@ -2645,11 +2617,11 @@
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        _env->ThrowNew(IAEClass, "m == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2694,11 +2666,11 @@
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        _env->ThrowNew(IAEClass, "m == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -3079,11 +3051,11 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3110,7 +3082,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -3162,7 +3134,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glTexEnvfv(
@@ -3197,11 +3169,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3228,7 +3200,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -3280,7 +3252,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glTexEnvxv(
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index f17ef21..1154cef 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -2,21 +2,23 @@
 **
 ** Copyright 2009, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -28,10 +30,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -42,7 +40,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -64,26 +62,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -104,13 +82,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -123,7 +101,6 @@
 }
 
 // --------------------------------------------------------------------------
-
 /* GLbitfield glQueryMatrixxOES ( GLfixed *mantissa, GLint *exponent ) */
 static jint
 android_glQueryMatrixxOES___3II_3II
@@ -139,18 +116,18 @@
 
     if (!mantissa_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "mantissa == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissa == null");
         goto exit;
     }
     if (mantissaOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "mantissaOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissaOffset < 0");
         goto exit;
     }
     _mantissaRemaining = _env->GetArrayLength(mantissa_ref) - mantissaOffset;
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - mantissaOffset < 16");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - mantissaOffset < 16");
         goto exit;
     }
     mantissa_base = (GLfixed *)
@@ -159,18 +136,18 @@
 
     if (!exponent_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "exponent == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponent == null");
         goto exit;
     }
     if (exponentOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "exponentOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponentOffset < 0");
         goto exit;
     }
     _exponentRemaining = _env->GetArrayLength(exponent_ref) - exponentOffset;
     if (_exponentRemaining < 16) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - exponentOffset < 16");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - exponentOffset < 16");
         goto exit;
     }
     exponent_base = (GLint *)
@@ -210,13 +187,13 @@
     mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining);
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 16");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
         goto exit;
     }
     exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining);
     if (_exponentRemaining < 16) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 16");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
         goto exit;
     }
     _returnValue = glQueryMatrixxOES(
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 1c326ba..d038f20 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -2,21 +2,23 @@
 **
 ** Copyright 2009, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -35,10 +37,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -49,7 +47,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -71,26 +69,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -111,13 +89,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -137,13 +115,13 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
 
 // --------------------------------------------------------------------------
-
 /* void glBindBuffer ( GLenum target, GLuint buffer ) */
 static void
 android_glBindBuffer__II
@@ -165,7 +143,7 @@
     if (data_buf) {
         data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
         if (_remaining < size) {
-            _env->ThrowNew(IAEClass, "remaining() < size");
+            jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
             goto exit;
         }
     }
@@ -192,7 +170,7 @@
 
     data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
     if (_remaining < size) {
-        _env->ThrowNew(IAEClass, "remaining() < size");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
         goto exit;
     }
     glBufferSubData(
@@ -217,11 +195,11 @@
     GLfloat *equation = (GLfloat *) 0;
 
     if (!equation_ref) {
-        _env->ThrowNew(IAEClass, "equation == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -268,11 +246,11 @@
     GLfixed *equation = (GLfixed *) 0;
 
     if (!equation_ref) {
-        _env->ThrowNew(IAEClass, "equation == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -343,16 +321,16 @@
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
-        _env->ThrowNew(IAEClass, "buffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -381,7 +359,7 @@
 
     buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glDeleteBuffers(
@@ -418,18 +396,18 @@
 
     if (!buffers_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "buffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -460,7 +438,7 @@
     buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glGenBuffers(
@@ -485,12 +463,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -540,18 +518,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLint *)
@@ -583,7 +561,7 @@
     params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetBufferParameteriv(
@@ -609,12 +587,12 @@
 
     if (!eqn_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "eqn == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -664,12 +642,12 @@
 
     if (!eqn_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "eqn == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -719,12 +697,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -774,12 +752,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -829,12 +807,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -882,7 +860,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -956,7 +934,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetLightfv(
@@ -982,12 +960,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1035,7 +1013,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1109,7 +1087,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetLightxv(
@@ -1135,12 +1113,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1174,7 +1152,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1234,7 +1212,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetMaterialfv(
@@ -1260,12 +1238,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1299,7 +1277,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1359,7 +1337,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetMaterialxv(
@@ -1385,12 +1363,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1418,7 +1396,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1472,7 +1450,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetTexEnvfv(
@@ -1498,12 +1476,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1531,7 +1509,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLint *)
@@ -1585,7 +1563,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetTexEnviv(
@@ -1611,12 +1589,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1644,7 +1622,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1698,7 +1676,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetTexEnvxv(
@@ -1724,18 +1702,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1767,7 +1745,7 @@
     params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetTexParameterfv(
@@ -1793,18 +1771,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLint *)
@@ -1836,7 +1814,7 @@
     params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetTexParameteriv(
@@ -1862,18 +1840,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -1905,7 +1883,7 @@
     params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetTexParameterxv(
@@ -1983,16 +1961,16 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2021,7 +1999,7 @@
 
     params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glPointParameterfv(
@@ -2054,16 +2032,16 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2092,7 +2070,7 @@
 
     params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glPointParameterxv(
@@ -2160,11 +2138,11 @@
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2191,7 +2169,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLint *)
@@ -2243,7 +2221,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glTexEnviv(
@@ -2267,16 +2245,16 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2306,7 +2284,7 @@
 
     params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glTexParameterfv(
@@ -2341,16 +2319,16 @@
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLint *)
@@ -2380,7 +2358,7 @@
 
     params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glTexParameteriv(
@@ -2404,16 +2382,16 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2443,7 +2421,7 @@
 
     params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glTexParameterxv(
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index 1390506..d6dc0fe 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -2,21 +2,23 @@
 **
 ** Copyright 2009, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -37,10 +39,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -51,7 +49,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -73,26 +71,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -113,13 +91,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -139,12 +117,12 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
 // --------------------------------------------------------------------------
-
 /* void glBlendEquationSeparateOES ( GLenum modeRGB, GLenum modeAlpha ) */
 static void
 android_glBlendEquationSeparateOES__II
@@ -224,16 +202,16 @@
     GLshort *coords = (GLshort *) 0;
 
     if (!coords_ref) {
-        _env->ThrowNew(IAEClass, "coords == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "length - offset < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
         goto exit;
     }
     coords_base = (GLshort *)
@@ -261,7 +239,7 @@
 
     coords = (GLshort *)getPointer(_env, coords_buf, &_array, &_remaining);
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "remaining() < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
         goto exit;
     }
     glDrawTexsvOES(
@@ -283,16 +261,16 @@
     GLint *coords = (GLint *) 0;
 
     if (!coords_ref) {
-        _env->ThrowNew(IAEClass, "coords == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "length - offset < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
         goto exit;
     }
     coords_base = (GLint *)
@@ -320,7 +298,7 @@
 
     coords = (GLint *)getPointer(_env, coords_buf, &_array, &_remaining);
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "remaining() < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
         goto exit;
     }
     glDrawTexivOES(
@@ -342,16 +320,16 @@
     GLfixed *coords = (GLfixed *) 0;
 
     if (!coords_ref) {
-        _env->ThrowNew(IAEClass, "coords == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "length - offset < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
         goto exit;
     }
     coords_base = (GLfixed *)
@@ -379,7 +357,7 @@
 
     coords = (GLfixed *)getPointer(_env, coords_buf, &_array, &_remaining);
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "remaining() < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
         goto exit;
     }
     glDrawTexxvOES(
@@ -414,16 +392,16 @@
     GLfloat *coords = (GLfloat *) 0;
 
     if (!coords_ref) {
-        _env->ThrowNew(IAEClass, "coords == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "length - offset < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
         goto exit;
     }
     coords_base = (GLfloat *)
@@ -451,7 +429,7 @@
 
     coords = (GLfloat *)getPointer(_env, coords_buf, &_array, &_remaining);
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "remaining() < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
         goto exit;
     }
     glDrawTexfvOES(
@@ -542,11 +520,11 @@
     GLfixed *equation = (GLfixed *) 0;
 
     if (!equation_ref) {
-        _env->ThrowNew(IAEClass, "equation == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -625,11 +603,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -692,18 +670,18 @@
 
     if (!eqn_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "eqn == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
     if (_remaining < 4) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 4");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
         goto exit;
     }
     eqn_base = (GLfixed *)
@@ -734,7 +712,7 @@
     eqn = (GLfixed *)getPointer(_env, eqn_buf, &_array, &_remaining);
     if (_remaining < 4) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 4");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
         goto exit;
     }
     glGetClipPlanexOES(
@@ -759,12 +737,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -814,12 +792,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -871,12 +849,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -928,12 +906,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -985,12 +963,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1050,11 +1028,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1112,11 +1090,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1174,11 +1152,11 @@
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        _env->ThrowNew(IAEClass, "m == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -1234,11 +1212,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1287,11 +1265,11 @@
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        _env->ThrowNew(IAEClass, "m == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -1384,11 +1362,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1498,11 +1476,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1562,11 +1540,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1647,16 +1625,16 @@
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
-        _env->ThrowNew(IAEClass, "renderbuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -1685,7 +1663,7 @@
 
     renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glDeleteRenderbuffersOES(
@@ -1710,18 +1688,18 @@
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "renderbuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -1752,7 +1730,7 @@
     renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glGenRenderbuffersOES(
@@ -1789,18 +1767,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLint *)
@@ -1832,7 +1810,7 @@
     params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetRenderbufferParameterivOES(
@@ -1877,16 +1855,16 @@
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
-        _env->ThrowNew(IAEClass, "framebuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -1915,7 +1893,7 @@
 
     framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glDeleteFramebuffersOES(
@@ -1940,18 +1918,18 @@
 
     if (!framebuffers_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "framebuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -1982,7 +1960,7 @@
     framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glGenFramebuffersOES(
@@ -2043,18 +2021,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLint *)
@@ -2087,7 +2065,7 @@
     params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetFramebufferAttachmentParameterivOES(
@@ -2221,11 +2199,11 @@
     GLfloat *equation = (GLfloat *) 0;
 
     if (!equation_ref) {
-        _env->ThrowNew(IAEClass, "equation == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
@@ -2274,18 +2252,18 @@
 
     if (!eqn_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "eqn == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
     if (_remaining < 4) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 4");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
         goto exit;
     }
     eqn_base = (GLfloat *)
@@ -2316,7 +2294,7 @@
     eqn = (GLfloat *)getPointer(_env, eqn_buf, &_array, &_remaining);
     if (_remaining < 4) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 4");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
         goto exit;
     }
     glGetClipPlanefOES(
@@ -2359,11 +2337,11 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2423,11 +2401,11 @@
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2487,11 +2465,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2542,12 +2520,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2599,12 +2577,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2656,12 +2634,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index 7ac0f6e..a53e4d7 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -2,21 +2,23 @@
 **
 ** Copyright 2009, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -28,10 +30,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -42,7 +40,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -64,26 +62,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -104,13 +82,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -130,7 +108,8 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
@@ -148,7 +127,6 @@
 }
 
 // --------------------------------------------------------------------------
-
 /* void glActiveTexture ( GLenum texture ) */
 static void
 android_glActiveTexture__I
@@ -175,7 +153,7 @@
     const char* _nativename = 0;
 
     if (!name) {
-        _env->ThrowNew(IAEClass, "name == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
         goto exit;
     }
     _nativename = _env->GetStringUTFChars(name, 0);
@@ -297,7 +275,7 @@
     if (data_buf) {
         data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
         if (_remaining < size) {
-            _env->ThrowNew(IAEClass, "remaining() < size");
+            jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
             goto exit;
         }
     }
@@ -324,7 +302,7 @@
 
     data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
     if (_remaining < size) {
-        _env->ThrowNew(IAEClass, "remaining() < size");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
         goto exit;
     }
     glBufferSubData(
@@ -530,16 +508,16 @@
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
-        _env->ThrowNew(IAEClass, "buffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -568,7 +546,7 @@
 
     buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glDeleteBuffers(
@@ -591,11 +569,11 @@
     GLuint *framebuffers = (GLuint *) 0;
 
     if (!framebuffers_ref) {
-        _env->ThrowNew(IAEClass, "framebuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
@@ -651,11 +629,11 @@
     GLuint *renderbuffers = (GLuint *) 0;
 
     if (!renderbuffers_ref) {
-        _env->ThrowNew(IAEClass, "renderbuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
@@ -711,16 +689,16 @@
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
-        _env->ThrowNew(IAEClass, "textures == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     textures_base = (GLuint *)
@@ -749,7 +727,7 @@
 
     textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glDeleteTextures(
@@ -852,7 +830,7 @@
 
     indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining);
     if (_remaining < count) {
-        _env->ThrowNew(AIOOBEClass, "remaining() < count");
+        jniThrowException(_env, "java/lang/ArrayIndexOutOfBoundsException", "remaining() < count");
         goto exit;
     }
     glDrawElements(
@@ -945,18 +923,18 @@
 
     if (!buffers_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "buffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -987,7 +965,7 @@
     buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glGenBuffers(
@@ -1021,12 +999,12 @@
 
     if (!framebuffers_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "framebuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
@@ -1076,12 +1054,12 @@
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "renderbuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
@@ -1131,18 +1109,18 @@
 
     if (!textures_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "textures == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     textures_base = (GLuint *)
@@ -1173,7 +1151,7 @@
     textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glGenTextures(
@@ -1207,12 +1185,12 @@
 
     if (!length_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length == null");
         goto exit;
     }
     if (lengthOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "lengthOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "lengthOffset < 0");
         goto exit;
     }
     _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
@@ -1222,12 +1200,12 @@
 
     if (!size_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "size == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "size == null");
         goto exit;
     }
     if (sizeOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "sizeOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "sizeOffset < 0");
         goto exit;
     }
     _sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
@@ -1237,12 +1215,12 @@
 
     if (!type_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "type == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "type == null");
         goto exit;
     }
     if (typeOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "typeOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "typeOffset < 0");
         goto exit;
     }
     _typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
@@ -1252,12 +1230,12 @@
 
     if (!name_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "name == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
         goto exit;
     }
     if (nameOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "nameOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "nameOffset < 0");
         goto exit;
     }
     _nameRemaining = _env->GetArrayLength(name_ref) - nameOffset;
@@ -1352,12 +1330,12 @@
 
     if (!length_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length == null");
         goto exit;
     }
     if (lengthOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "lengthOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "lengthOffset < 0");
         goto exit;
     }
     _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
@@ -1367,12 +1345,12 @@
 
     if (!size_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "size == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "size == null");
         goto exit;
     }
     if (sizeOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "sizeOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "sizeOffset < 0");
         goto exit;
     }
     _sizeRemaining = _env->GetArrayLength(size_ref) - sizeOffset;
@@ -1382,12 +1360,12 @@
 
     if (!type_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "type == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "type == null");
         goto exit;
     }
     if (typeOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "typeOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "typeOffset < 0");
         goto exit;
     }
     _typeRemaining = _env->GetArrayLength(type_ref) - typeOffset;
@@ -1397,12 +1375,12 @@
 
     if (!name_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "name == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
         goto exit;
     }
     if (nameOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "nameOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "nameOffset < 0");
         goto exit;
     }
     _nameRemaining = _env->GetArrayLength(name_ref) - nameOffset;
@@ -1491,12 +1469,12 @@
 
     if (!count_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "count == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "count == null");
         goto exit;
     }
     if (countOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "countOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "countOffset < 0");
         goto exit;
     }
     _countRemaining = _env->GetArrayLength(count_ref) - countOffset;
@@ -1506,12 +1484,12 @@
 
     if (!shaders_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "shaders == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "shaders == null");
         goto exit;
     }
     if (shadersOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "shadersOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "shadersOffset < 0");
         goto exit;
     }
     _shadersRemaining = _env->GetArrayLength(shaders_ref) - shadersOffset;
@@ -1573,7 +1551,7 @@
     const char* _nativename = 0;
 
     if (!name) {
-        _env->ThrowNew(IAEClass, "name == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
         goto exit;
     }
     _nativename = _env->GetStringUTFChars(name, 0);
@@ -1602,12 +1580,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1657,18 +1635,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLint *)
@@ -1700,7 +1678,7 @@
     params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetBufferParameteriv(
@@ -1735,12 +1713,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1790,12 +1768,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1849,12 +1827,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2191,7 +2169,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLint *)
@@ -2553,7 +2531,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetIntegerv(
@@ -2578,12 +2556,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2624,32 +2602,24 @@
     }
 }
 
-#include <string.h>
+#include <stdlib.h>
 
 /* void glGetProgramInfoLog ( GLuint shader, GLsizei maxLength, GLsizei* length, GLchar* infoLog ) */
-static
-jstring
-android_glGetProgramInfoLog (JNIEnv *_env, jobject _this, jint shader) {
+static jstring android_glGetProgramInfoLog(JNIEnv *_env, jobject, jint shader) {
     GLint infoLen = 0;
-    jstring _result = 0;
-    char* buf = 0;
     glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
-    if (infoLen) {
-        char* buf = (char*) malloc(infoLen);
-        if (buf == 0) {
-            _env->ThrowNew(IAEClass, "out of memory");
-            goto exit;
-        }
-        glGetProgramInfoLog(shader, infoLen, NULL, buf);
-        _result = _env->NewStringUTF(buf);
-    } else {
-        _result = _env->NewStringUTF("");
+    if (!infoLen) {
+        return _env->NewStringUTF("");
     }
-exit:
-    if (buf) {
-            free(buf);
+    char* buf = (char*) malloc(infoLen);
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
     }
-    return _result;
+    glGetProgramInfoLog(shader, infoLen, NULL, buf);
+    jstring result = _env->NewStringUTF(buf);
+    free(buf);
+    return result;
 }
 /* void glGetRenderbufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
 static void
@@ -2662,12 +2632,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2719,12 +2689,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2765,32 +2735,24 @@
     }
 }
 
-#include <string.h>
+#include <stdlib.h>
 
 /* void glGetShaderInfoLog ( GLuint shader, GLsizei maxLength, GLsizei* length, GLchar* infoLog ) */
-static
-jstring
-android_glGetShaderInfoLog (JNIEnv *_env, jobject _this, jint shader) {
+static jstring android_glGetShaderInfoLog(JNIEnv *_env, jobject, jint shader) {
     GLint infoLen = 0;
-    jstring _result = 0;
-    char* buf = 0;
     glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
-    if (infoLen) {
-        char* buf = (char*) malloc(infoLen);
-        if (buf == 0) {
-            _env->ThrowNew(IAEClass, "out of memory");
-            goto exit;
-        }
-        glGetShaderInfoLog(shader, infoLen, NULL, buf);
-        _result = _env->NewStringUTF(buf);
-    } else {
-        _result = _env->NewStringUTF("");
+    if (!infoLen) {
+        return _env->NewStringUTF("");
     }
-exit:
-    if (buf) {
-            free(buf);
+    char* buf = (char*) malloc(infoLen);
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
     }
-    return _result;
+    glGetShaderInfoLog(shader, infoLen, NULL, buf);
+    jstring result = _env->NewStringUTF(buf);
+    free(buf);
+    return result;
 }
 /* void glGetShaderPrecisionFormat ( GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision ) */
 static void
@@ -2806,12 +2768,12 @@
 
     if (!range_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "range == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "range == null");
         goto exit;
     }
     if (rangeOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "rangeOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "rangeOffset < 0");
         goto exit;
     }
     _rangeRemaining = _env->GetArrayLength(range_ref) - rangeOffset;
@@ -2821,12 +2783,12 @@
 
     if (!precision_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "precision == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "precision == null");
         goto exit;
     }
     if (precisionOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "precisionOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "precisionOffset < 0");
         goto exit;
     }
     _precisionRemaining = _env->GetArrayLength(precision_ref) - precisionOffset;
@@ -2894,12 +2856,12 @@
 
     if (!length_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length == null");
         goto exit;
     }
     if (lengthOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "lengthOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "lengthOffset < 0");
         goto exit;
     }
     _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
@@ -2909,12 +2871,12 @@
 
     if (!source_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "source == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "source == null");
         goto exit;
     }
     if (sourceOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "sourceOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "sourceOffset < 0");
         goto exit;
     }
     _sourceRemaining = _env->GetArrayLength(source_ref) - sourceOffset;
@@ -2961,16 +2923,10 @@
     }
 }
 
-#include <string.h>
-
 /* const GLubyte * glGetString ( GLenum name ) */
-static
-jstring
-android_glGetString
-  (JNIEnv *_env, jobject _this, jint name) {
-    const char * chars = (const char *)glGetString((GLenum)name);
-    jstring output = _env->NewStringUTF(chars);
-    return output;
+static jstring android_glGetString(JNIEnv* _env, jobject, jint name) {
+    const char* chars = (const char*) glGetString((GLenum) name);
+    return _env->NewStringUTF(chars);
 }
 /* void glGetTexParameterfv ( GLenum target, GLenum pname, GLfloat *params ) */
 static void
@@ -2983,18 +2939,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -3026,7 +2982,7 @@
     params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetTexParameterfv(
@@ -3052,18 +3008,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLint *)
@@ -3095,7 +3051,7 @@
     params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetTexParameteriv(
@@ -3121,12 +3077,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3178,12 +3134,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3232,7 +3188,7 @@
     const char* _nativename = 0;
 
     if (!name) {
-        _env->ThrowNew(IAEClass, "name == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "name == null");
         goto exit;
     }
     _nativename = _env->GetStringUTFChars(name, 0);
@@ -3261,12 +3217,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3318,12 +3274,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3566,11 +3522,11 @@
     GLvoid *binary = (GLvoid *) 0;
 
     if (!shaders_ref) {
-        _env->ThrowNew(IAEClass, "shaders == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "shaders == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _shadersRemaining = _env->GetArrayLength(shaders_ref) - offset;
@@ -3633,7 +3589,7 @@
     (JNIEnv *_env, jobject _this, jint shader, jstring string) {
 
     if (!string) {
-        _env->ThrowNew(IAEClass, "string == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "string == null");
         return;
     }
 
@@ -3754,16 +3710,16 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -3793,7 +3749,7 @@
 
     params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glTexParameterfv(
@@ -3828,16 +3784,16 @@
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLint *)
@@ -3867,7 +3823,7 @@
 
     params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glTexParameteriv(
@@ -3928,11 +3884,11 @@
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        _env->ThrowNew(IAEClass, "v == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -3991,11 +3947,11 @@
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        _env->ThrowNew(IAEClass, "v == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4055,11 +4011,11 @@
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        _env->ThrowNew(IAEClass, "v == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4119,11 +4075,11 @@
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        _env->ThrowNew(IAEClass, "v == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4184,11 +4140,11 @@
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        _env->ThrowNew(IAEClass, "v == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4249,11 +4205,11 @@
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        _env->ThrowNew(IAEClass, "v == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4315,11 +4271,11 @@
     GLfloat *v = (GLfloat *) 0;
 
     if (!v_ref) {
-        _env->ThrowNew(IAEClass, "v == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4381,11 +4337,11 @@
     GLint *v = (GLint *) 0;
 
     if (!v_ref) {
-        _env->ThrowNew(IAEClass, "v == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "v == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(v_ref) - offset;
@@ -4434,11 +4390,11 @@
     GLfloat *value = (GLfloat *) 0;
 
     if (!value_ref) {
-        _env->ThrowNew(IAEClass, "value == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "value == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(value_ref) - offset;
@@ -4489,11 +4445,11 @@
     GLfloat *value = (GLfloat *) 0;
 
     if (!value_ref) {
-        _env->ThrowNew(IAEClass, "value == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "value == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(value_ref) - offset;
@@ -4544,11 +4500,11 @@
     GLfloat *value = (GLfloat *) 0;
 
     if (!value_ref) {
-        _env->ThrowNew(IAEClass, "value == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "value == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(value_ref) - offset;
@@ -4627,11 +4583,11 @@
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        _env->ThrowNew(IAEClass, "values == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
@@ -4689,11 +4645,11 @@
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        _env->ThrowNew(IAEClass, "values == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
@@ -4752,11 +4708,11 @@
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        _env->ThrowNew(IAEClass, "values == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
@@ -4816,11 +4772,11 @@
     GLfloat *values = (GLfloat *) 0;
 
     if (!values_ref) {
-        _env->ThrowNew(IAEClass, "values == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "values == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(values_ref) - offset;
diff --git a/core/jni/android_os_ParcelFileDescriptor.cpp b/core/jni/android_os_ParcelFileDescriptor.cpp
index 1f737f9..bfa80e1 100644
--- a/core/jni/android_os_ParcelFileDescriptor.cpp
+++ b/core/jni/android_os_ParcelFileDescriptor.cpp
@@ -29,13 +29,6 @@
 namespace android
 {
 
-static struct file_descriptor_offsets_t
-{
-    jclass mClass;
-    jmethodID mConstructor;
-    jfieldID mDescriptor;
-} gFileDescriptorOffsets;
-
 static struct socket_offsets_t
 {
     jfieldID mSocketImpl;
@@ -57,13 +50,8 @@
 {
     jobject socketImpl = env->GetObjectField(object, gSocketOffsets.mSocketImpl);
     jobject fileDescriptor = env->GetObjectField(socketImpl, gSocketImplOffsets.mFileDescriptor);
-    jint fd = env->GetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor);
-    jobject fileDescriptorClone = env->NewObject(gFileDescriptorOffsets.mClass,
-        gFileDescriptorOffsets.mConstructor);
-    if (fileDescriptorClone != NULL) {
-        env->SetIntField(fileDescriptorClone, gFileDescriptorOffsets.mDescriptor, dup(fd));
-    }
-    return fileDescriptorClone;
+    jint fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+    return jniCreateFileDescriptor(env, dup(fd));
 }
 
 static int android_os_ParcelFileDescriptor_createPipeNative(JNIEnv* env,
@@ -75,11 +63,7 @@
     }
 
     for (int i=0; i<2; i++) {
-        jobject fdObj = env->NewObject(gFileDescriptorOffsets.mClass,
-                gFileDescriptorOffsets.mConstructor);
-        if (fdObj != NULL) {
-            env->SetIntField(fdObj, gFileDescriptorOffsets.mDescriptor, fds[i]);
-        }
+        jobject fdObj = jniCreateFileDescriptor(env, fds[i]);
         env->SetObjectArrayElement(outFds, i, fdObj);
     }
 
@@ -90,7 +74,7 @@
 {
     jobject descriptor = env->GetObjectField(clazz, gParcelFileDescriptorOffsets.mFileDescriptor);
     if (descriptor == NULL) return -1;
-    return env->GetIntField(descriptor, gFileDescriptorOffsets.mDescriptor);
+    return jniGetFDFromFileDescriptor(env, descriptor);
 }
 
 static jlong android_os_ParcelFileDescriptor_getStatSize(JNIEnv* env,
@@ -101,16 +85,16 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
         return -1;
     }
-    
+
     struct stat st;
     if (fstat(fd, &st) != 0) {
         return -1;
     }
-    
+
     if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
         return st.st_size;
     }
-    
+
     return -1;
 }
 
@@ -122,7 +106,7 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
         return -1;
     }
-    
+
     return lseek(fd, pos, SEEK_SET);
 }
 
@@ -168,14 +152,6 @@
     LOG_FATAL_IF(gSocketImplOffsets.mFileDescriptor == NULL,
                  "Unable to find fd field in java.net.SocketImpl");
 
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
-    gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
-    gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL,
-                 "Unable to find descriptor field in java.io.FileDescriptor");
-    
     clazz = env->FindClass(kParcelFileDescriptorPathName);
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
     gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 8ea7e90..b0e92e4 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -169,7 +169,7 @@
 
     env->ReleasePrimitiveArrayCritical(outOffsets, offsets, 0);
 
-    jobject fileDesc = newFileDescriptor(env, fd);
+    jobject fileDesc = jniCreateFileDescriptor(env, fd);
     if (fileDesc == NULL) {
         close(fd);
         return NULL;
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 8618b79..0681195 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -131,13 +131,6 @@
     jmethodID mLogE;
 } gLogOffsets;
 
-static struct file_descriptor_offsets_t
-{
-    jclass mClass;
-    jmethodID mConstructor;
-    jfieldID mDescriptor;
-} gFileDescriptorOffsets;
-
 static struct parcel_file_descriptor_offsets_t
 {
     jclass mClass;
@@ -591,17 +584,6 @@
     return NULL;
 }
 
-jobject newFileDescriptor(JNIEnv* env, int fd)
-{
-    jobject object = env->NewObject(
-            gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor);
-    if (object != NULL) {
-        //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd);
-        env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd);
-    }
-    return object;
-}
-
 jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc)
 {
     return env->NewObject(
@@ -1358,8 +1340,8 @@
 {
     Parcel* parcel = parcelForJavaObject(env, clazz);
     if (parcel != NULL) {
-        const status_t err = parcel->writeDupFileDescriptor(
-                env->GetIntField(object, gFileDescriptorOffsets.mDescriptor));
+        const status_t err =
+                parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
         if (err != NO_ERROR) {
             jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
         }
@@ -1459,13 +1441,7 @@
         if (fd < 0) return NULL;
         fd = dup(fd);
         if (fd < 0) return NULL;
-        jobject object = env->NewObject(
-                gFileDescriptorOffsets.mClass, gFileDescriptorOffsets.mConstructor);
-        if (object != NULL) {
-            //LOGI("Created new FileDescriptor %p with fd %d\n", object, fd);
-            env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, fd);
-        }
-        return object;
+        return jniCreateFileDescriptor(env, fd);
     }
     return NULL;
 }
@@ -1512,7 +1488,7 @@
         jniThrowException(env, "java/io/FileNotFoundException", strerror(errno));
         return NULL;
     }
-    jobject object = newFileDescriptor(env, fd);
+    jobject object = jniCreateFileDescriptor(env, fd);
     if (object == NULL) {
         close(fd);
     }
@@ -1525,7 +1501,7 @@
         jniThrowNullPointerException(env, NULL);
         return NULL;
     }
-    int origfd = env->GetIntField(orig, gFileDescriptorOffsets.mDescriptor);
+    int origfd = jniGetFDFromFileDescriptor(env, orig);
     if (origfd < 0) {
         jniThrowException(env, "java/lang/IllegalArgumentException", "bad FileDescriptor");
         return NULL;
@@ -1536,7 +1512,7 @@
         jniThrowIOException(env, errno);
         return NULL;
     }
-    jobject object = newFileDescriptor(env, fd);
+    jobject object = jniCreateFileDescriptor(env, fd);
     if (object == NULL) {
         close(fd);
     }
@@ -1549,9 +1525,9 @@
         jniThrowNullPointerException(env, NULL);
         return;
     }
-    int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, object);
     if (fd >= 0) {
-        env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1);
+        jniSetFileDescriptorOfFD(env, object, -1);
         //LOGI("Closing ParcelFileDescriptor %d\n", fd);
         close(fd);
     }
@@ -1563,9 +1539,9 @@
         jniThrowNullPointerException(env, NULL);
         return;
     }
-    int fd = env->GetIntField(object, gFileDescriptorOffsets.mDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, object);
     if (fd >= 0) {
-        env->SetIntField(object, gFileDescriptorOffsets.mDescriptor, -1);
+        jniSetFileDescriptorOfFD(env, object, -1);
     }
 }
 
@@ -1794,15 +1770,6 @@
         clazz, "e", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Throwable;)I");
     assert(gLogOffsets.mLogE);
 
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
-    gFileDescriptorOffsets.mConstructor
-        = env->GetMethodID(clazz, "<init>", "()V");
-    gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL,
-                 "Unable to find descriptor field in java.io.FileDescriptor");
-
     clazz = env->FindClass("android/os/ParcelFileDescriptor");
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
     gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
@@ -1842,13 +1809,3 @@
         return -1;
     return 0;
 }
-
-namespace android {
-
-// Returns the Unix file descriptor for a ParcelFileDescriptor object
-int getParcelFileDescriptorFD(JNIEnv* env, jobject object)
-{
-    return env->GetIntField(object, gFileDescriptorOffsets.mDescriptor);
-}
-
-}
diff --git a/core/jni/android_util_Binder.h b/core/jni/android_util_Binder.h
index 495e76a..0122691 100644
--- a/core/jni/android_util_Binder.h
+++ b/core/jni/android_util_Binder.h
@@ -2,16 +2,16 @@
 **
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
@@ -29,7 +29,6 @@
 // Note: does not type checking; must guarantee jobject is a Java Parcel
 extern Parcel* parcelForJavaObject(JNIEnv* env, jobject obj);
 
-extern jobject newFileDescriptor(JNIEnv* env, int fd);
 extern jobject newParcelFileDescriptor(JNIEnv* env, jobject fileDesc);
 
 }
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index f31bba9..314c2ee 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -595,13 +595,11 @@
 // Logging
 // ----------------------------------------------------------------------------
 
-jfieldID gFileDescriptorField;
-
 static void
 android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor)
 {
 #ifdef USE_OPENGL_RENDERER
-    int fd = env->GetIntField(javaFileDescriptor, gFileDescriptorField);
+    int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
     android::uirenderer::DisplayList::outputLogBuffer(fd);
 #endif // USE_OPENGL_RENDERER
 }
@@ -736,12 +734,6 @@
 
 int register_android_app_ActivityThread(JNIEnv* env)
 {
-    jclass fileDescriptorClass = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    gFileDescriptorField = env->GetFieldID(fileDescriptorClass, "descriptor", "I");
-    LOG_FATAL_IF(gFileDescriptorField == NULL,
-                 "Unable to find descriptor field in java.io.FileDescriptor");
-
     return AndroidRuntime::registerNativeMethods(
             env, kActivityThreadPathName,
             gActivityThreadMethods, NELEM(gActivityThreadMethods));
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index bf613e1..8777131 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -2,21 +2,23 @@
 **
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -64,10 +66,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jclass G11ImplClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
@@ -85,7 +83,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -115,26 +113,6 @@
         _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
 }
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -155,7 +133,7 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     if (*array == NULL) {
@@ -164,7 +142,7 @@
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -208,7 +186,8 @@
                 releasePointer(_env, array, buf, 0);
             }
         } else {
-            _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+            jniThrowException(_env, "java/lang/IllegalArgumentException",
+                              "Must use a native order direct Buffer");
         }
     }
     return buf;
@@ -251,7 +230,7 @@
         }
     }
 }
-    
+
 static bool
 checkForExtension(const GLubyte* pExtensions, const GLubyte* pExtension) {
     for (;*pExtensions != '\0'; pExtensions = nextExtension(pExtensions)) {
@@ -280,7 +259,6 @@
 }
 
 // --------------------------------------------------------------------------
-
 /* void glActiveTexture ( GLenum texture ) */
 static void
 android_glActiveTexture__I
@@ -557,16 +535,16 @@
     GLuint *textures = (GLuint *) 0;
 
     if (!textures_ref) {
-        _env->ThrowNew(IAEClass, "textures == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     textures_base = (GLuint *)
@@ -595,7 +573,7 @@
 
     textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glDeleteTextures(
@@ -686,7 +664,7 @@
 
     indices = (GLvoid *)getPointer(_env, indices_buf, &_array, &_remaining);
     if (_remaining < count) {
-        _env->ThrowNew(AIOOBEClass, "remaining() < count");
+        jniThrowException(_env, "java/lang/ArrayIndexOutOfBoundsException", "remaining() < count");
         goto exit;
     }
     glDrawElements(
@@ -753,11 +731,11 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -787,7 +765,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -841,7 +819,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glFogfv(
@@ -874,11 +852,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -908,7 +886,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -962,7 +940,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glFogxv(
@@ -1024,18 +1002,18 @@
 
     if (!textures_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "textures == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "textures == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(textures_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     textures_base = (GLuint *)
@@ -1066,7 +1044,7 @@
     textures = (GLuint *)getPointer(_env, textures_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glGenTextures(
@@ -1100,12 +1078,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1442,7 +1420,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLint *)
@@ -1804,7 +1782,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetIntegerv(
@@ -1818,16 +1796,10 @@
     }
 }
 
-#include <string.h>
-
 /* const GLubyte * glGetString ( GLenum name ) */
-static
-jstring
-android_glGetString
-  (JNIEnv *_env, jobject _this, jint name) {
-    const char * chars = (const char *)glGetString((GLenum)name);
-    jstring output = _env->NewStringUTF(chars);
-    return output;
+static jstring android_glGetString(JNIEnv *_env, jobject, jint name) {
+    const char* chars = (const char*) glGetString((GLenum) name);
+    return _env->NewStringUTF(chars);
 }
 /* void glHint ( GLenum target, GLenum mode ) */
 static void
@@ -1858,11 +1830,11 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1883,7 +1855,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -1928,7 +1900,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glLightModelfv(
@@ -1961,11 +1933,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -1986,7 +1958,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2031,7 +2003,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glLightModelxv(
@@ -2065,11 +2037,11 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2116,7 +2088,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2188,7 +2160,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glLightfv(
@@ -2223,11 +2195,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2274,7 +2246,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2346,7 +2318,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glLightxv(
@@ -2395,11 +2367,11 @@
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        _env->ThrowNew(IAEClass, "m == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2444,11 +2416,11 @@
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        _env->ThrowNew(IAEClass, "m == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2513,11 +2485,11 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2550,7 +2522,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -2608,7 +2580,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glMaterialfv(
@@ -2643,11 +2615,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -2680,7 +2652,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -2738,7 +2710,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glMaterialxv(
@@ -2771,11 +2743,11 @@
     GLfloat *m = (GLfloat *) 0;
 
     if (!m_ref) {
-        _env->ThrowNew(IAEClass, "m == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -2820,11 +2792,11 @@
     GLfixed *m = (GLfixed *) 0;
 
     if (!m_ref) {
-        _env->ThrowNew(IAEClass, "m == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "m == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(m_ref) - offset;
@@ -3205,11 +3177,11 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3236,7 +3208,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -3288,7 +3260,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glTexEnvfv(
@@ -3323,11 +3295,11 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -3354,7 +3326,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -3406,7 +3378,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glTexEnvxv(
@@ -3569,18 +3541,18 @@
 
     if (!mantissa_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "mantissa == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissa == null");
         goto exit;
     }
     if (mantissaOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "mantissaOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "mantissaOffset < 0");
         goto exit;
     }
     _mantissaRemaining = _env->GetArrayLength(mantissa_ref) - mantissaOffset;
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - mantissaOffset < 16");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - mantissaOffset < 16");
         goto exit;
     }
     mantissa_base = (GLfixed *)
@@ -3589,18 +3561,18 @@
 
     if (!exponent_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "exponent == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponent == null");
         goto exit;
     }
     if (exponentOffset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "exponentOffset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "exponentOffset < 0");
         goto exit;
     }
     _exponentRemaining = _env->GetArrayLength(exponent_ref) - exponentOffset;
     if (_exponentRemaining < 16) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - exponentOffset < 16");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - exponentOffset < 16");
         goto exit;
     }
     exponent_base = (GLint *)
@@ -3640,13 +3612,13 @@
     mantissa = (GLfixed *)getPointer(_env, mantissa_buf, &_mantissaArray, &_mantissaRemaining);
     if (_mantissaRemaining < 16) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 16");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
         goto exit;
     }
     exponent = (GLint *)getPointer(_env, exponent_buf, &_exponentArray, &_exponentRemaining);
     if (_exponentRemaining < 16) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 16");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 16");
         goto exit;
     }
     _returnValue = glQueryMatrixxOES(
@@ -3685,7 +3657,7 @@
     if (data_buf) {
         data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
         if (_remaining < size) {
-            _env->ThrowNew(IAEClass, "remaining() < size");
+            jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
             goto exit;
         }
     }
@@ -3712,7 +3684,7 @@
 
     data = (GLvoid *)getPointer(_env, data_buf, &_array, &_remaining);
     if (_remaining < size) {
-        _env->ThrowNew(IAEClass, "remaining() < size");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < size");
         goto exit;
     }
     glBufferSubData(
@@ -3737,16 +3709,16 @@
     GLfloat *equation = (GLfloat *) 0;
 
     if (!equation_ref) {
-        _env->ThrowNew(IAEClass, "equation == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
     if (_remaining < 4) {
-        _env->ThrowNew(IAEClass, "length - offset < 4");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
         goto exit;
     }
     equation_base = (GLfloat *)
@@ -3775,7 +3747,7 @@
 
     equation = (GLfloat *)getPointer(_env, equation_buf, &_array, &_remaining);
     if (_remaining < 4) {
-        _env->ThrowNew(IAEClass, "remaining() < 4");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
         goto exit;
     }
     glClipPlanef(
@@ -3798,16 +3770,16 @@
     GLfixed *equation = (GLfixed *) 0;
 
     if (!equation_ref) {
-        _env->ThrowNew(IAEClass, "equation == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "equation == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(equation_ref) - offset;
     if (_remaining < 4) {
-        _env->ThrowNew(IAEClass, "length - offset < 4");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 4");
         goto exit;
     }
     equation_base = (GLfixed *)
@@ -3836,7 +3808,7 @@
 
     equation = (GLfixed *)getPointer(_env, equation_buf, &_array, &_remaining);
     if (_remaining < 4) {
-        _env->ThrowNew(IAEClass, "remaining() < 4");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 4");
         goto exit;
     }
     glClipPlanex(
@@ -3883,16 +3855,16 @@
     GLuint *buffers = (GLuint *) 0;
 
     if (!buffers_ref) {
-        _env->ThrowNew(IAEClass, "buffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -3921,7 +3893,7 @@
 
     buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
     if (_remaining < n) {
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glDeleteBuffers(
@@ -3958,18 +3930,18 @@
 
     if (!buffers_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "buffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "buffers == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(buffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     buffers_base = (GLuint *)
@@ -4000,7 +3972,7 @@
     buffers = (GLuint *)getPointer(_env, buffers_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glGenBuffers(
@@ -4025,12 +3997,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4073,7 +4045,7 @@
 static void
 android_glGetBufferParameteriv__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
-    _env->ThrowNew(UOEClass,
+    jniThrowException(_env, "java/lang/UnsupportedOperationException",
         "glGetBufferParameteriv");
 }
 
@@ -4081,7 +4053,7 @@
 static void
 android_glGetBufferParameteriv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
-    _env->ThrowNew(UOEClass,
+    jniThrowException(_env, "java/lang/UnsupportedOperationException",
         "glGetBufferParameteriv");
 }
 
@@ -4096,12 +4068,12 @@
 
     if (!eqn_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "eqn == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -4151,12 +4123,12 @@
 
     if (!eqn_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "eqn == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "eqn == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(eqn_ref) - offset;
@@ -4206,12 +4178,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4261,12 +4233,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4316,12 +4288,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4369,7 +4341,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -4443,7 +4415,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetLightfv(
@@ -4469,12 +4441,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4522,7 +4494,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -4596,7 +4568,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetLightxv(
@@ -4622,12 +4594,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4661,7 +4633,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -4721,7 +4693,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetMaterialfv(
@@ -4747,12 +4719,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4786,7 +4758,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -4846,7 +4818,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetMaterialxv(
@@ -4872,12 +4844,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -4905,7 +4877,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLint *)
@@ -4959,7 +4931,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetTexEnviv(
@@ -4985,12 +4957,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -5018,7 +4990,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5072,7 +5044,7 @@
     }
     if (_remaining < _needed) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glGetTexEnvxv(
@@ -5098,18 +5070,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -5141,7 +5113,7 @@
     params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetTexParameterfv(
@@ -5167,18 +5139,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLint *)
@@ -5210,7 +5182,7 @@
     params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetTexParameteriv(
@@ -5236,18 +5208,18 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5279,7 +5251,7 @@
     params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glGetTexParameterxv(
@@ -5357,16 +5329,16 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -5395,7 +5367,7 @@
 
     params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glPointParameterfv(
@@ -5428,16 +5400,16 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5466,7 +5438,7 @@
 
     params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glPointParameterxv(
@@ -5534,11 +5506,11 @@
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -5565,7 +5537,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "length - offset < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < needed");
         goto exit;
     }
     params_base = (GLint *)
@@ -5617,7 +5589,7 @@
             break;
     }
     if (_remaining < _needed) {
-        _env->ThrowNew(IAEClass, "remaining() < needed");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < needed");
         goto exit;
     }
     glTexEnviv(
@@ -5641,16 +5613,16 @@
     GLfloat *params = (GLfloat *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfloat *)
@@ -5680,7 +5652,7 @@
 
     params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glTexParameterfv(
@@ -5715,16 +5687,16 @@
     GLint *params = (GLint *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLint *)
@@ -5754,7 +5726,7 @@
 
     params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glTexParameteriv(
@@ -5778,16 +5750,16 @@
     GLfixed *params = (GLfixed *) 0;
 
     if (!params_ref) {
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "length - offset < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 1");
         goto exit;
     }
     params_base = (GLfixed *)
@@ -5817,7 +5789,7 @@
 
     params = (GLfixed *)getPointer(_env, params_buf, &_array, &_remaining);
     if (_remaining < 1) {
-        _env->ThrowNew(IAEClass, "remaining() < 1");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 1");
         goto exit;
     }
     glTexParameterxv(
@@ -5875,16 +5847,16 @@
     GLfloat *coords = (GLfloat *) 0;
 
     if (!coords_ref) {
-        _env->ThrowNew(IAEClass, "coords == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "length - offset < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
         goto exit;
     }
     coords_base = (GLfloat *)
@@ -5912,7 +5884,7 @@
 
     coords = (GLfloat *)getPointer(_env, coords_buf, &_array, &_remaining);
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "remaining() < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
         goto exit;
     }
     glDrawTexfvOES(
@@ -5947,16 +5919,16 @@
     GLint *coords = (GLint *) 0;
 
     if (!coords_ref) {
-        _env->ThrowNew(IAEClass, "coords == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "length - offset < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
         goto exit;
     }
     coords_base = (GLint *)
@@ -5984,7 +5956,7 @@
 
     coords = (GLint *)getPointer(_env, coords_buf, &_array, &_remaining);
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "remaining() < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
         goto exit;
     }
     glDrawTexivOES(
@@ -6019,16 +5991,16 @@
     GLshort *coords = (GLshort *) 0;
 
     if (!coords_ref) {
-        _env->ThrowNew(IAEClass, "coords == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "length - offset < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
         goto exit;
     }
     coords_base = (GLshort *)
@@ -6056,7 +6028,7 @@
 
     coords = (GLshort *)getPointer(_env, coords_buf, &_array, &_remaining);
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "remaining() < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
         goto exit;
     }
     glDrawTexsvOES(
@@ -6091,16 +6063,16 @@
     GLfixed *coords = (GLfixed *) 0;
 
     if (!coords_ref) {
-        _env->ThrowNew(IAEClass, "coords == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "coords == null");
         goto exit;
     }
     if (offset < 0) {
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(coords_ref) - offset;
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "length - offset < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < 5");
         goto exit;
     }
     coords_base = (GLfixed *)
@@ -6128,7 +6100,7 @@
 
     coords = (GLfixed *)getPointer(_env, coords_buf, &_array, &_remaining);
     if (_remaining < 5) {
-        _env->ThrowNew(IAEClass, "remaining() < 5");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < 5");
         goto exit;
     }
     glDrawTexxvOES(
@@ -6223,7 +6195,7 @@
 android_glBindFramebufferOES__II
   (JNIEnv *_env, jobject _this, jint target, jint framebuffer) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glBindFramebufferOES");
             return;
     }
@@ -6238,7 +6210,7 @@
 android_glBindRenderbufferOES__II
   (JNIEnv *_env, jobject _this, jint target, jint renderbuffer) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glBindRenderbufferOES");
             return;
     }
@@ -6253,7 +6225,7 @@
 android_glBlendEquation__I
   (JNIEnv *_env, jobject _this, jint mode) {
     if (! supportsExtension(_env, _this, have_OES_blend_subtractID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glBlendEquation");
             return;
     }
@@ -6267,7 +6239,7 @@
 android_glBlendEquationSeparate__II
   (JNIEnv *_env, jobject _this, jint modeRGB, jint modeAlpha) {
     if (! supportsExtension(_env, _this, have_OES_blend_equation_separateID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glBlendEquationSeparate");
             return;
     }
@@ -6282,7 +6254,7 @@
 android_glBlendFuncSeparate__IIII
   (JNIEnv *_env, jobject _this, jint srcRGB, jint dstRGB, jint srcAlpha, jint dstAlpha) {
     if (! supportsExtension(_env, _this, have_OES_blend_equation_separateID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glBlendFuncSeparate");
             return;
     }
@@ -6299,7 +6271,7 @@
 android_glCheckFramebufferStatusOES__I
   (JNIEnv *_env, jobject _this, jint target) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glCheckFramebufferStatusOES");
             return 0;
     }
@@ -6315,7 +6287,7 @@
 android_glDeleteFramebuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glDeleteFramebuffersOES");
             return;
     }
@@ -6326,18 +6298,18 @@
 
     if (!framebuffers_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "framebuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -6361,7 +6333,7 @@
 android_glDeleteFramebuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glDeleteFramebuffersOES");
             return;
     }
@@ -6373,7 +6345,7 @@
     framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glDeleteFramebuffersOES(
@@ -6392,7 +6364,7 @@
 android_glDeleteRenderbuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glDeleteRenderbuffersOES");
             return;
     }
@@ -6403,18 +6375,18 @@
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "renderbuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -6438,7 +6410,7 @@
 android_glDeleteRenderbuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glDeleteRenderbuffersOES");
             return;
     }
@@ -6450,7 +6422,7 @@
     renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glDeleteRenderbuffersOES(
@@ -6469,7 +6441,7 @@
 android_glFramebufferRenderbufferOES__IIII
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint renderbuffertarget, jint renderbuffer) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glFramebufferRenderbufferOES");
             return;
     }
@@ -6486,7 +6458,7 @@
 android_glFramebufferTexture2DOES__IIIII
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint textarget, jint texture, jint level) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glFramebufferTexture2DOES");
             return;
     }
@@ -6504,7 +6476,7 @@
 android_glGenerateMipmapOES__I
   (JNIEnv *_env, jobject _this, jint target) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGenerateMipmapOES");
             return;
     }
@@ -6518,7 +6490,7 @@
 android_glGenFramebuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray framebuffers_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGenFramebuffersOES");
             return;
     }
@@ -6529,18 +6501,18 @@
 
     if (!framebuffers_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "framebuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "framebuffers == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(framebuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     framebuffers_base = (GLuint *)
@@ -6564,7 +6536,7 @@
 android_glGenFramebuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject framebuffers_buf) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGenFramebuffersOES");
             return;
     }
@@ -6576,7 +6548,7 @@
     framebuffers = (GLuint *)getPointer(_env, framebuffers_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glGenFramebuffersOES(
@@ -6595,7 +6567,7 @@
 android_glGenRenderbuffersOES__I_3II
   (JNIEnv *_env, jobject _this, jint n, jintArray renderbuffers_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGenRenderbuffersOES");
             return;
     }
@@ -6606,18 +6578,18 @@
 
     if (!renderbuffers_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "renderbuffers == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "renderbuffers == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(renderbuffers_ref) - offset;
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "length - offset < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "length - offset < n");
         goto exit;
     }
     renderbuffers_base = (GLuint *)
@@ -6641,7 +6613,7 @@
 android_glGenRenderbuffersOES__ILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint n, jobject renderbuffers_buf) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGenRenderbuffersOES");
             return;
     }
@@ -6653,7 +6625,7 @@
     renderbuffers = (GLuint *)getPointer(_env, renderbuffers_buf, &_array, &_remaining);
     if (_remaining < n) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "remaining() < n");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "remaining() < n");
         goto exit;
     }
     glGenRenderbuffersOES(
@@ -6672,7 +6644,7 @@
 android_glGetFramebufferAttachmentParameterivOES__III_3II
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jintArray params_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGetFramebufferAttachmentParameterivOES");
             return;
     }
@@ -6683,12 +6655,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6715,7 +6687,7 @@
 android_glGetFramebufferAttachmentParameterivOES__IIILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint attachment, jint pname, jobject params_buf) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGetFramebufferAttachmentParameterivOES");
             return;
     }
@@ -6741,7 +6713,7 @@
 android_glGetRenderbufferParameterivOES__II_3II
   (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGetRenderbufferParameterivOES");
             return;
     }
@@ -6752,12 +6724,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6783,7 +6755,7 @@
 android_glGetRenderbufferParameterivOES__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGetRenderbufferParameterivOES");
             return;
     }
@@ -6808,7 +6780,7 @@
 android_glGetTexGenfv__II_3FI
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGetTexGenfv");
             return;
     }
@@ -6819,12 +6791,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6850,7 +6822,7 @@
 android_glGetTexGenfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGetTexGenfv");
             return;
     }
@@ -6875,7 +6847,7 @@
 android_glGetTexGeniv__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGetTexGeniv");
             return;
     }
@@ -6886,12 +6858,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6917,7 +6889,7 @@
 android_glGetTexGeniv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGetTexGeniv");
             return;
     }
@@ -6942,7 +6914,7 @@
 android_glGetTexGenxv__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGetTexGenxv");
             return;
     }
@@ -6953,12 +6925,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -6984,7 +6956,7 @@
 android_glGetTexGenxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glGetTexGenxv");
             return;
     }
@@ -7009,7 +6981,7 @@
 android_glIsFramebufferOES__I
   (JNIEnv *_env, jobject _this, jint framebuffer) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glIsFramebufferOES");
             return JNI_FALSE;
     }
@@ -7025,7 +6997,7 @@
 android_glIsRenderbufferOES__I
   (JNIEnv *_env, jobject _this, jint renderbuffer) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glIsRenderbufferOES");
             return JNI_FALSE;
     }
@@ -7041,7 +7013,7 @@
 android_glRenderbufferStorageOES__IIII
   (JNIEnv *_env, jobject _this, jint target, jint internalformat, jint width, jint height) {
     if (! supportsExtension(_env, _this, have_OES_framebuffer_objectID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glRenderbufferStorageOES");
             return;
     }
@@ -7058,7 +7030,7 @@
 android_glTexGenf__IIF
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloat param) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glTexGenf");
             return;
     }
@@ -7074,7 +7046,7 @@
 android_glTexGenfv__II_3FI
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jfloatArray params_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glTexGenfv");
             return;
     }
@@ -7085,12 +7057,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -7116,7 +7088,7 @@
 android_glTexGenfv__IILjava_nio_FloatBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glTexGenfv");
             return;
     }
@@ -7141,7 +7113,7 @@
 android_glTexGeni__III
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jint param) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glTexGeni");
             return;
     }
@@ -7157,7 +7129,7 @@
 android_glTexGeniv__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glTexGeniv");
             return;
     }
@@ -7168,12 +7140,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -7199,7 +7171,7 @@
 android_glTexGeniv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glTexGeniv");
             return;
     }
@@ -7224,7 +7196,7 @@
 android_glTexGenx__III
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jint param) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glTexGenx");
             return;
     }
@@ -7240,7 +7212,7 @@
 android_glTexGenxv__II_3II
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jintArray params_ref, jint offset) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glTexGenxv");
             return;
     }
@@ -7251,12 +7223,12 @@
 
     if (!params_ref) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "params == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "params == null");
         goto exit;
     }
     if (offset < 0) {
         _exception = 1;
-        _env->ThrowNew(IAEClass, "offset < 0");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset < 0");
         goto exit;
     }
     _remaining = _env->GetArrayLength(params_ref) - offset;
@@ -7282,7 +7254,7 @@
 android_glTexGenxv__IILjava_nio_IntBuffer_2
   (JNIEnv *_env, jobject _this, jint coord, jint pname, jobject params_buf) {
     if (! supportsExtension(_env, _this, have_OES_texture_cube_mapID)) {
-        _env->ThrowNew(UOEClass,
+        jniThrowException(_env, "java/lang/UnsupportedOperationException",
             "glTexGenxv");
             return;
     }
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index db3e9d9..c97eec3 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -151,7 +151,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flugmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flugmodus ist AN."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flugmodus ist AUS."</string>
-    <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"100 +"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5833510281787786290">"Mehr als 100"</string>
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Kostenpflichtige Dienste"</string>
@@ -465,7 +465,7 @@
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6594393334785738252">"Ermöglicht der Anwendung Schreiben in USB-Speicher"</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="6643963204976471878">"Ermöglicht einer Anwendung, auf die SD-Karte zu schreiben"</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"Intern. Mediensp. änd./löschen"</string>
-    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Ermöglicht es einer Anwendung, den Inhalt des internen Medienspeichers zu ändern"</string>
+    <string name="permdesc_mediaStorageWrite" product="default" msgid="8232008512478316233">"Ermöglicht einer Anwendung, den Inhalt des internen Medienspeichers zu ändern"</string>
     <string name="permlab_cache_filesystem" msgid="5656487264819669824">"Zugriff auf das Cache-Dateisystem"</string>
     <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"Gewährt einer Anwendung Lese- und Schreibzugriff auf das Cache-Dateisystem."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"Internetanrufe tätigen/annehmen"</string>
diff --git a/core/tests/coretests/src/com/android/internal/util/HierarchicalStateMachineTest.java b/core/tests/coretests/src/com/android/internal/util/HierarchicalStateMachineTest.java
index 36666c4..b6f8be5 100644
--- a/core/tests/coretests/src/com/android/internal/util/HierarchicalStateMachineTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/HierarchicalStateMachineTest.java
@@ -24,7 +24,7 @@
 
 import com.android.internal.util.HierarchicalState;
 import com.android.internal.util.HierarchicalStateMachine;
-import com.android.internal.util.ProcessedMessages;
+import com.android.internal.util.HierarchicalStateMachine.ProcessedMessageInfo;
 
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -125,21 +125,21 @@
 
         assertTrue(smQuitTest.getProcessedMessagesCount() == 9);
 
-        ProcessedMessages.Info pmi;
+        ProcessedMessageInfo pmi;
 
         // The first two message didn't quit and were handled by mS1
-        pmi = smQuitTest.getProcessedMessage(6);
+        pmi = smQuitTest.getProcessedMessageInfo(6);
         assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
         assertEquals(smQuitTest.mS1, pmi.getState());
         assertEquals(smQuitTest.mS1, pmi.getOriginalState());
 
-        pmi = smQuitTest.getProcessedMessage(7);
+        pmi = smQuitTest.getProcessedMessageInfo(7);
         assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
         assertEquals(smQuitTest.mS1, pmi.getState());
         assertEquals(smQuitTest.mS1, pmi.getOriginalState());
 
         // The last message was never handled so the states are null
-        pmi = smQuitTest.getProcessedMessage(8);
+        pmi = smQuitTest.getProcessedMessageInfo(8);
         assertEquals(HierarchicalStateMachine.HSM_QUIT_CMD, pmi.getWhat());
         assertEquals(null, pmi.getState());
         assertEquals(null, pmi.getOriginalState());
@@ -285,10 +285,10 @@
 
         assertTrue(smEnterExitTranstionToTest.getProcessedMessagesCount() == 1);
 
-        ProcessedMessages.Info pmi;
+        ProcessedMessageInfo pmi;
 
         // Message should be handled by mS2.
-        pmi = smEnterExitTranstionToTest.getProcessedMessage(0);
+        pmi = smEnterExitTranstionToTest.getProcessedMessageInfo(0);
         assertEquals(TEST_CMD_1, pmi.getWhat());
         assertEquals(smEnterExitTranstionToTest.mS2, pmi.getState());
         assertEquals(smEnterExitTranstionToTest.mS2, pmi.getOriginalState());
@@ -369,18 +369,18 @@
         assertTrue(sm0.getProcessedMessagesCount() == 6);
         assertTrue(sm0.getProcessedMessagesSize() == 3);
 
-        ProcessedMessages.Info pmi;
-        pmi = sm0.getProcessedMessage(0);
+        ProcessedMessageInfo pmi;
+        pmi = sm0.getProcessedMessageInfo(0);
         assertEquals(TEST_CMD_4, pmi.getWhat());
         assertEquals(sm0.mS1, pmi.getState());
         assertEquals(sm0.mS1, pmi.getOriginalState());
 
-        pmi = sm0.getProcessedMessage(1);
+        pmi = sm0.getProcessedMessageInfo(1);
         assertEquals(TEST_CMD_5, pmi.getWhat());
         assertEquals(sm0.mS1, pmi.getState());
         assertEquals(sm0.mS1, pmi.getOriginalState());
 
-        pmi = sm0.getProcessedMessage(2);
+        pmi = sm0.getProcessedMessageInfo(2);
         assertEquals(TEST_CMD_6, pmi.getWhat());
         assertEquals(sm0.mS1, pmi.getState());
         assertEquals(sm0.mS1, pmi.getOriginalState());
@@ -469,13 +469,13 @@
 
         assertTrue(sm1.getProcessedMessagesSize() == 2);
 
-        ProcessedMessages.Info pmi;
-        pmi = sm1.getProcessedMessage(0);
+        ProcessedMessageInfo pmi;
+        pmi = sm1.getProcessedMessageInfo(0);
         assertEquals(TEST_CMD_1, pmi.getWhat());
         assertEquals(sm1.mS1, pmi.getState());
         assertEquals(sm1.mS1, pmi.getOriginalState());
 
-        pmi = sm1.getProcessedMessage(1);
+        pmi = sm1.getProcessedMessageInfo(1);
         assertEquals(TEST_CMD_2, pmi.getWhat());
         assertEquals(sm1.mS1, pmi.getState());
         assertEquals(sm1.mS1, pmi.getOriginalState());
@@ -571,20 +571,20 @@
 
         assertTrue(sm2.getProcessedMessagesSize() == 4);
 
-        ProcessedMessages.Info pmi;
-        pmi = sm2.getProcessedMessage(0);
+        ProcessedMessageInfo pmi;
+        pmi = sm2.getProcessedMessageInfo(0);
         assertEquals(TEST_CMD_1, pmi.getWhat());
         assertEquals(sm2.mS1, pmi.getState());
 
-        pmi = sm2.getProcessedMessage(1);
+        pmi = sm2.getProcessedMessageInfo(1);
         assertEquals(TEST_CMD_2, pmi.getWhat());
         assertEquals(sm2.mS1, pmi.getState());
 
-        pmi = sm2.getProcessedMessage(2);
+        pmi = sm2.getProcessedMessageInfo(2);
         assertEquals(TEST_CMD_1, pmi.getWhat());
         assertEquals(sm2.mS2, pmi.getState());
 
-        pmi = sm2.getProcessedMessage(3);
+        pmi = sm2.getProcessedMessageInfo(3);
         assertEquals(TEST_CMD_2, pmi.getWhat());
         assertEquals(sm2.mS2, pmi.getState());
 
@@ -663,13 +663,13 @@
 
         assertTrue(sm3.getProcessedMessagesSize() == 2);
 
-        ProcessedMessages.Info pmi;
-        pmi = sm3.getProcessedMessage(0);
+        ProcessedMessageInfo pmi;
+        pmi = sm3.getProcessedMessageInfo(0);
         assertEquals(TEST_CMD_1, pmi.getWhat());
         assertEquals(sm3.mParentState, pmi.getState());
         assertEquals(sm3.mChildState, pmi.getOriginalState());
 
-        pmi = sm3.getProcessedMessage(1);
+        pmi = sm3.getProcessedMessageInfo(1);
         assertEquals(TEST_CMD_2, pmi.getWhat());
         assertEquals(sm3.mParentState, pmi.getState());
         assertEquals(sm3.mChildState, pmi.getOriginalState());
@@ -757,13 +757,13 @@
 
         assertTrue(sm4.getProcessedMessagesSize() == 2);
 
-        ProcessedMessages.Info pmi;
-        pmi = sm4.getProcessedMessage(0);
+        ProcessedMessageInfo pmi;
+        pmi = sm4.getProcessedMessageInfo(0);
         assertEquals(TEST_CMD_1, pmi.getWhat());
         assertEquals(sm4.mChildState1, pmi.getState());
         assertEquals(sm4.mChildState1, pmi.getOriginalState());
 
-        pmi = sm4.getProcessedMessage(1);
+        pmi = sm4.getProcessedMessageInfo(1);
         assertEquals(TEST_CMD_2, pmi.getWhat());
         assertEquals(sm4.mParentState, pmi.getState());
         assertEquals(sm4.mChildState2, pmi.getOriginalState());
@@ -1050,33 +1050,33 @@
         assertEquals(1, sm5.mChildState5EnterCount);
         assertEquals(1, sm5.mChildState5ExitCount);
 
-        ProcessedMessages.Info pmi;
-        pmi = sm5.getProcessedMessage(0);
+        ProcessedMessageInfo pmi;
+        pmi = sm5.getProcessedMessageInfo(0);
         assertEquals(TEST_CMD_1, pmi.getWhat());
         assertEquals(sm5.mChildState1, pmi.getState());
         assertEquals(sm5.mChildState1, pmi.getOriginalState());
 
-        pmi = sm5.getProcessedMessage(1);
+        pmi = sm5.getProcessedMessageInfo(1);
         assertEquals(TEST_CMD_2, pmi.getWhat());
         assertEquals(sm5.mChildState2, pmi.getState());
         assertEquals(sm5.mChildState2, pmi.getOriginalState());
 
-        pmi = sm5.getProcessedMessage(2);
+        pmi = sm5.getProcessedMessageInfo(2);
         assertEquals(TEST_CMD_3, pmi.getWhat());
         assertEquals(sm5.mChildState5, pmi.getState());
         assertEquals(sm5.mChildState5, pmi.getOriginalState());
 
-        pmi = sm5.getProcessedMessage(3);
+        pmi = sm5.getProcessedMessageInfo(3);
         assertEquals(TEST_CMD_4, pmi.getWhat());
         assertEquals(sm5.mChildState3, pmi.getState());
         assertEquals(sm5.mChildState3, pmi.getOriginalState());
 
-        pmi = sm5.getProcessedMessage(4);
+        pmi = sm5.getProcessedMessageInfo(4);
         assertEquals(TEST_CMD_5, pmi.getWhat());
         assertEquals(sm5.mChildState4, pmi.getState());
         assertEquals(sm5.mChildState4, pmi.getOriginalState());
 
-        pmi = sm5.getProcessedMessage(5);
+        pmi = sm5.getProcessedMessageInfo(5);
         assertEquals(TEST_CMD_6, pmi.getWhat());
         assertEquals(sm5.mParentState2, pmi.getState());
         assertEquals(sm5.mParentState2, pmi.getOriginalState());
@@ -1434,7 +1434,7 @@
         for (StateMachineSharedThread sm : sms) {
             assertTrue(sm.getProcessedMessagesCount() == 4);
             for (int i = 0; i < sm.getProcessedMessagesCount(); i++) {
-                ProcessedMessages.Info pmi = sm.getProcessedMessage(i);
+                ProcessedMessageInfo pmi = sm.getProcessedMessageInfo(i);
                 assertEquals(i+1, pmi.getWhat());
                 assertEquals(sm.mS1, pmi.getState());
                 assertEquals(sm.mS1, pmi.getOriginalState());
@@ -1464,37 +1464,37 @@
         }
 
         assertEquals(7, sm.getProcessedMessagesCount());
-        ProcessedMessages.Info pmi = sm.getProcessedMessage(0);
+        ProcessedMessageInfo pmi = sm.getProcessedMessageInfo(0);
         assertEquals(Hsm1.CMD_1, pmi.getWhat());
         assertEquals(sm.mS1, pmi.getState());
         assertEquals(sm.mS1, pmi.getOriginalState());
 
-        pmi = sm.getProcessedMessage(1);
+        pmi = sm.getProcessedMessageInfo(1);
         assertEquals(Hsm1.CMD_2, pmi.getWhat());
         assertEquals(sm.mP1, pmi.getState());
         assertEquals(sm.mS1, pmi.getOriginalState());
 
-        pmi = sm.getProcessedMessage(2);
+        pmi = sm.getProcessedMessageInfo(2);
         assertEquals(Hsm1.CMD_2, pmi.getWhat());
         assertEquals(sm.mS2, pmi.getState());
         assertEquals(sm.mS2, pmi.getOriginalState());
 
-        pmi = sm.getProcessedMessage(3);
+        pmi = sm.getProcessedMessageInfo(3);
         assertEquals(Hsm1.CMD_3, pmi.getWhat());
         assertEquals(sm.mS2, pmi.getState());
         assertEquals(sm.mS2, pmi.getOriginalState());
 
-        pmi = sm.getProcessedMessage(4);
+        pmi = sm.getProcessedMessageInfo(4);
         assertEquals(Hsm1.CMD_3, pmi.getWhat());
         assertEquals(sm.mP2, pmi.getState());
         assertEquals(sm.mP2, pmi.getOriginalState());
 
-        pmi = sm.getProcessedMessage(5);
+        pmi = sm.getProcessedMessageInfo(5);
         assertEquals(Hsm1.CMD_4, pmi.getWhat());
         assertEquals(sm.mP2, pmi.getState());
         assertEquals(sm.mP2, pmi.getOriginalState());
 
-        pmi = sm.getProcessedMessage(6);
+        pmi = sm.getProcessedMessageInfo(6);
         assertEquals(Hsm1.CMD_5, pmi.getWhat());
         assertEquals(sm.mP2, pmi.getState());
         assertEquals(sm.mP2, pmi.getOriginalState());
diff --git a/include/android_runtime/AndroidRuntime.h b/include/android_runtime/AndroidRuntime.h
index 22c9b72..de2d50b 100644
--- a/include/android_runtime/AndroidRuntime.h
+++ b/include/android_runtime/AndroidRuntime.h
@@ -56,7 +56,7 @@
     status_t callMain(const char* className, int argc, const char* const argv[]);
 
     /**
-     * Find a class, with the input either of the form 
+     * Find a class, with the input either of the form
      * "package/class" or "package.class".
      */
     static jclass findClass(JNIEnv* env, const char* className);
@@ -67,7 +67,7 @@
     void start();       // start in android.util.RuntimeInit
 
     static AndroidRuntime* getRuntime();
-    
+
     /**
      * This gets called after the JavaVM has initialized.  Override it
      * with the system's native entry point.
@@ -112,7 +112,7 @@
      * Thread creation helpers.
      */
     static int javaCreateThreadEtc(
-                                android_thread_func_t entryFunction, 
+                                android_thread_func_t entryFunction,
                                 void* userData,
                                 const char* threadName,
                                 int32_t threadPriority,
@@ -121,9 +121,6 @@
     static int javaThreadShell(void* args);
 };
 
-// Returns the Unix file descriptor for a ParcelFileDescriptor object
-extern int getParcelFileDescriptorFD(JNIEnv* env, jobject object);
-
 extern CursorWindow * get_window_from_object(JNIEnv * env, jobject javaWindow);
 
 }
diff --git a/libs/usb/src/com/android/future/usb/UsbManager.java b/libs/usb/src/com/android/future/usb/UsbManager.java
index d424b63..91d8e8a 100644
--- a/libs/usb/src/com/android/future/usb/UsbManager.java
+++ b/libs/usb/src/com/android/future/usb/UsbManager.java
@@ -28,7 +28,7 @@
 import android.util.Log;
 
 /**
- * This class allows you to access the state of USB, both in host and device mode.
+ * This is a wrapper class for the USB Manager to support USB accessories.
  *
  * <p>You can obtain an instance of this class by calling {@link #getInstance}
  *
@@ -141,7 +141,7 @@
     /**
      * Returns true if the caller has permission to access the accessory.
      * Permission might have been granted temporarily via
-     * {@link #requestPermission(android.hardware.usb.UsbAccessory} or
+     * {@link #requestPermission} or
      * by the user choosing the caller as the default application for the accessory.
      *
      * @param accessory to check permissions for
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index a219623..2ba9b3f 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -241,7 +241,7 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return;
     }
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     if (offset < 0 || length < 0 || fd < 0) {
         if (offset < 0) {
             LOGE("negative offset (%lld)", offset);
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index ecbd288..aa0adf3 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -325,7 +325,7 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return;
     }
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     LOGV("setDataSourceFD: fd %d", fd);
     process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." );
 }
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index a8a46c1..4750b0b 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -253,7 +253,7 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return;
     }
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
     status_t opStatus = mr->setOutputFile(fd, offset, length);
     process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed.");
@@ -267,7 +267,7 @@
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return;
     }
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
     status_t opStatus = mr->setOutputFileAuxiliary(fd);
     process_media_recorder_call(env, opStatus, "java/io/IOException", "setOutputFile failed.");
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index 06058dc..043f373 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -303,7 +303,7 @@
         return NULL;
     }
 
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
     char* data = mp->extractAlbumArt(fd);
     if (!data) {
         return NULL;
@@ -426,5 +426,3 @@
     return AndroidRuntime::registerNativeMethods(env,
                 kClassMediaScanner, gMethods, NELEM(gMethods));
 }
-
-
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index 447f931..03d3388 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -60,7 +60,7 @@
     LOGV("android_media_SoundPool_load_FD");
     SoundPool *ap = MusterSoundPool(env, thiz);
     if (ap == NULL) return 0;
-    return ap->load(getParcelFileDescriptorFD(env, fileDescriptor),
+    return ap->load(jniGetFDFromFileDescriptor(env, fileDescriptor),
             int64_t(offset), int64_t(length), int(priority));
 }
 
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f31c2ac..9bd329df 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#undef DEBUG_HDCP
+#define DEBUG_HDCP
 
 //#define LOG_NDEBUG 0
 #define LOG_TAG "AwesomePlayer"
@@ -184,7 +184,8 @@
       mFlags(0),
       mExtractorFlags(0),
       mVideoBuffer(NULL),
-      mDecryptHandle(NULL) {
+      mDecryptHandle(NULL),
+      mLastVideoTimeUs(-1) {
     CHECK_EQ(mClient.connect(), (status_t)OK);
 
     DataSource::RegisterDefaultSniffers();
@@ -470,28 +471,13 @@
 
     mVideoRenderer.clear();
 
-    if (mVideoBuffer) {
-        mVideoBuffer->release();
-        mVideoBuffer = NULL;
-    }
-
     if (mRTSPController != NULL) {
         mRTSPController->disconnect();
         mRTSPController.clear();
     }
 
     if (mVideoSource != NULL) {
-        mVideoSource->stop();
-
-        // The following hack is necessary to ensure that the OMX
-        // component is completely released by the time we may try
-        // to instantiate it again.
-        wp<MediaSource> tmp = mVideoSource;
-        mVideoSource.clear();
-        while (tmp.promote() != NULL) {
-            usleep(1000);
-        }
-        IPCThreadState::self()->flushCommands();
+        shutdownVideoDecoder_l();
     }
 
     mDurationUs = -1;
@@ -510,6 +496,7 @@
     mFileSource.clear();
 
     mBitrate = -1;
+    mLastVideoTimeUs = -1;
 }
 
 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
@@ -1012,7 +999,7 @@
     Mutex::Autolock autoLock(mLock);
 
     mSurface = surface;
-    mNativeWindow = surface;
+    setNativeWindow_l(surface);
 }
 
 void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) {
@@ -1020,9 +1007,57 @@
 
     mSurface.clear();
     if (surfaceTexture != NULL) {
-        mNativeWindow = new SurfaceTextureClient(surfaceTexture);
+        setNativeWindow_l(new SurfaceTextureClient(surfaceTexture));
+    }
+}
+
+void AwesomePlayer::shutdownVideoDecoder_l() {
+    if (mVideoBuffer) {
+        mVideoBuffer->release();
+        mVideoBuffer = NULL;
     }
 
+    mVideoSource->stop();
+
+    // The following hack is necessary to ensure that the OMX
+    // component is completely released by the time we may try
+    // to instantiate it again.
+    wp<MediaSource> tmp = mVideoSource;
+    mVideoSource.clear();
+    while (tmp.promote() != NULL) {
+        usleep(1000);
+    }
+    IPCThreadState::self()->flushCommands();
+}
+
+void AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
+    mNativeWindow = native;
+
+    if (mVideoSource == NULL) {
+        return;
+    }
+
+    LOGI("attempting to reconfigure to use new surface");
+
+    bool wasPlaying = (mFlags & PLAYING) != 0;
+
+    pause_l();
+    mVideoRenderer.clear();
+
+    shutdownVideoDecoder_l();
+
+    CHECK_EQ(initVideoDecoder(), (status_t)OK);
+
+    if (mLastVideoTimeUs >= 0) {
+        mSeeking = SEEK;
+        mSeekNotificationSent = true;
+        mSeekTimeUs = mLastVideoTimeUs;
+        mFlags &= ~(AT_EOS | AUDIO_AT_EOS | VIDEO_AT_EOS);
+    }
+
+    if (wasPlaying) {
+        play_l();
+    }
 }
 
 void AwesomePlayer::setAudioSink(
@@ -1412,6 +1447,8 @@
     int64_t timeUs;
     CHECK(mVideoBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
 
+    mLastVideoTimeUs = timeUs;
+
     if (mSeeking == SEEK_VIDEO_ONLY) {
         if (mSeekTimeUs > timeUs) {
             LOGI("XXX mSeekTimeUs = %lld us, timeUs = %lld us",
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 03ce202..4bdfc6f 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -48,7 +48,7 @@
 bool MP3Extractor::get_mp3_frame_size(
         uint32_t header, size_t *frame_size,
         int *out_sampling_rate, int *out_channels,
-        int *out_bitrate) {
+        int *out_bitrate, int *out_num_samples) {
     *frame_size = 0;
 
     if (out_sampling_rate) {
@@ -63,6 +63,10 @@
         *out_bitrate = 0;
     }
 
+    if (out_num_samples) {
+        *out_num_samples = 1152;
+    }
+
     if ((header & 0xffe00000) != 0xffe00000) {
         return false;
     }
@@ -127,6 +131,10 @@
         }
 
         *frame_size = (12000 * bitrate / sampling_rate + padding) * 4;
+
+        if (out_num_samples) {
+            *out_num_samples = 384;
+        }
     } else {
         // layer II or III
 
@@ -150,10 +158,17 @@
             bitrate = (layer == 2 /* L2 */)
                 ? kBitrateV1L2[bitrate_index - 1]
                 : kBitrateV1L3[bitrate_index - 1];
+
+            if (out_num_samples) {
+                *out_num_samples = 1152;
+            }
         } else {
             // V2 (or 2.5)
 
             bitrate = kBitrateV2[bitrate_index - 1];
+            if (out_num_samples) {
+                *out_num_samples = 576;
+            }
         }
 
         if (out_bitrate) {
@@ -374,6 +389,9 @@
     sp<MP3Seeker> mSeeker;
     MediaBufferGroup *mGroup;
 
+    int64_t mBasisTimeUs;
+    int64_t mSamplesRead;
+
     MP3Source(const MP3Source &);
     MP3Source &operator=(const MP3Source &);
 };
@@ -489,7 +507,9 @@
       mCurrentTimeUs(0),
       mStarted(false),
       mSeeker(seeker),
-      mGroup(NULL) {
+      mGroup(NULL),
+      mBasisTimeUs(0),
+      mSamplesRead(0) {
 }
 
 MP3Source::~MP3Source() {
@@ -509,6 +529,9 @@
     mCurrentPos = mFirstFramePos;
     mCurrentTimeUs = 0;
 
+    mBasisTimeUs = mCurrentTimeUs;
+    mSamplesRead = 0;
+
     mStarted = true;
 
     return OK;
@@ -552,6 +575,9 @@
         } else {
             mCurrentTimeUs = actualSeekTimeUs;
         }
+
+        mBasisTimeUs = mCurrentTimeUs;
+        mSamplesRead = 0;
     }
 
     MediaBuffer *buffer;
@@ -562,6 +588,8 @@
 
     size_t frame_size;
     int bitrate;
+    int num_samples;
+    int sample_rate;
     for (;;) {
         ssize_t n = mDataSource->readAt(mCurrentPos, buffer->data(), 4);
         if (n < 4) {
@@ -575,7 +603,7 @@
 
         if ((header & kMask) == (mFixedHeader & kMask)
             && MP3Extractor::get_mp3_frame_size(
-                header, &frame_size, NULL, NULL, &bitrate)) {
+                header, &frame_size, &sample_rate, NULL, &bitrate, &num_samples)) {
             break;
         }
 
@@ -613,7 +641,9 @@
     buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
 
     mCurrentPos += frame_size;
-    mCurrentTimeUs += frame_size * 8000ll / bitrate;
+
+    mSamplesRead += num_samples;
+    mCurrentTimeUs = mBasisTimeUs + ((mSamplesRead * 1000000) / sample_rate);
 
     *out = buffer;
 
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 4095fbf..7621f2c 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -146,7 +146,8 @@
 
     int64_t thumbNailTime;
     if (frameTimeUs < 0) {
-        if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
+        if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)
+                || thumbNailTime < 0) {
             thumbNailTime = 0;
         }
         options.setSeekTo(thumbNailTime, mode);
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 7fd7724..8c61064 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -218,6 +218,8 @@
     DrmManagerClient *mDrmManagerClient;
     sp<DecryptHandle> mDecryptHandle;
 
+    int64_t mLastVideoTimeUs;
+
     status_t setDataSource_l(
             const char *uri,
             const KeyedVector<String8, String8> *headers = NULL);
@@ -267,6 +269,9 @@
 
     status_t startAudioPlayer_l();
 
+    void shutdownVideoDecoder_l();
+    void setNativeWindow_l(const sp<ANativeWindow> &native);
+
     AwesomePlayer(const AwesomePlayer &);
     AwesomePlayer &operator=(const AwesomePlayer &);
 };
diff --git a/media/libstagefright/include/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h
index ef71b8f..cf1146b 100644
--- a/media/libstagefright/include/MP3Extractor.h
+++ b/media/libstagefright/include/MP3Extractor.h
@@ -42,7 +42,7 @@
     static bool get_mp3_frame_size(
             uint32_t header, size_t *frame_size,
             int *out_sampling_rate = NULL, int *out_channels = NULL,
-            int *out_bitrate = NULL);
+            int *out_bitrate = NULL, int *out_num_samples = NULL);
 
 private:
     status_t mInitCheck;
diff --git a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
index ed1af49..9bd8f36 100644
--- a/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
+++ b/nfc-extras/java/com/android/nfc_extras/NfcAdapterExtras.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.nfc.ApduList;
 import android.nfc.INfcAdapterExtras;
 import android.nfc.NfcAdapter;
 import android.os.RemoteException;
@@ -184,4 +185,20 @@
     public NfcExecutionEnvironment getEmbeddedExecutionEnvironment() {
         return sEmbeddedEe;
     }
+
+    public void registerTearDownApdus(String packageName, ApduList apdus) {
+        try {
+            sService.registerTearDownApdus(packageName, apdus);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
+    }
+
+    public void unregisterTearDownApdus(String packageName) {
+        try {
+            sService.unregisterTearDownApdus(packageName);
+        } catch (RemoteException e) {
+            Log.e(TAG, "", e);
+        }
+    }
 }
diff --git a/opengl/java/android/opengl/GLES10.java b/opengl/java/android/opengl/GLES10.java
index 7c0f949..790acbd 100644
--- a/opengl/java/android/opengl/GLES10.java
+++ b/opengl/java/android/opengl/GLES10.java
@@ -1,18 +1,19 @@
 /*
- * Copyright (C) 2009 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.
- */
+**
+** Copyright 2009, 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.
+*/
 
 // This source file is automatically generated
 
diff --git a/opengl/java/android/opengl/GLES10Ext.java b/opengl/java/android/opengl/GLES10Ext.java
index 116ab9d..81fc59e 100644
--- a/opengl/java/android/opengl/GLES10Ext.java
+++ b/opengl/java/android/opengl/GLES10Ext.java
@@ -1,18 +1,19 @@
 /*
- * Copyright (C) 2009 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.
- */
+**
+** Copyright 2009, 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.
+*/
 
 // This source file is automatically generated
 
diff --git a/opengl/java/android/opengl/GLES11.java b/opengl/java/android/opengl/GLES11.java
index b24c043..1ca179b 100644
--- a/opengl/java/android/opengl/GLES11.java
+++ b/opengl/java/android/opengl/GLES11.java
@@ -1,18 +1,19 @@
 /*
- * Copyright (C) 2009 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.
- */
+**
+** Copyright 2009, 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.
+*/
 
 // This source file is automatically generated
 
diff --git a/opengl/java/android/opengl/GLES11Ext.java b/opengl/java/android/opengl/GLES11Ext.java
index a9a7a22..25d5467 100644
--- a/opengl/java/android/opengl/GLES11Ext.java
+++ b/opengl/java/android/opengl/GLES11Ext.java
@@ -1,18 +1,19 @@
 /*
- * Copyright (C) 2009 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.
- */
+**
+** Copyright 2009, 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.
+*/
 
 // This source file is automatically generated
 
diff --git a/opengl/java/android/opengl/GLES20.java b/opengl/java/android/opengl/GLES20.java
index 700164b..635f811 100644
--- a/opengl/java/android/opengl/GLES20.java
+++ b/opengl/java/android/opengl/GLES20.java
@@ -1,18 +1,19 @@
 /*
- * Copyright (C) 2009 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.
- */
+**
+** Copyright 2009, 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.
+*/
 
 // This source file is automatically generated
 
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 50f6760..090c0cb7 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -1,18 +1,19 @@
-/*
- * Copyright (C) 2006 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.
- */
+/* //device/java/android/com/google/android/gles_jni/GLImpl.java
+**
+** Copyright 2006, 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.
+*/
 
 // This source file is automatically generated
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL.java b/opengl/java/javax/microedition/khronos/opengles/GL.java
index d5b60c6..3b78f3d 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL.java
@@ -1,18 +1,19 @@
-/*
- * Copyright (C) 2006 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.
- */
+/* //device/java/android/javax/microedition/khronos/opengles/GL.java
+**
+** Copyright 2006, 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 javax.microedition.khronos.opengles;
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL10.java b/opengl/java/javax/microedition/khronos/opengles/GL10.java
index f48ecde..4fcfb52 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL10.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL10.java
@@ -1,18 +1,19 @@
-/*
- * Copyright (C) 2006 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.
- */
+/* //device/java/android/javax/microedition/khronos/opengles/GL10.java
+**
+** Copyright 2006, 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.
+*/
 
 // This source file is automatically generated
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java b/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java
index f3252ab..562b20a 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL10Ext.java
@@ -1,18 +1,19 @@
-/*
- * Copyright (C) 2007 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.
- */
+/* //device/java/android/javax/microedition/khronos/opengles/GL10Ext.java
+**
+** Copyright 2007, 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.
+*/
 
 // This source file is automatically generated
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11.java b/opengl/java/javax/microedition/khronos/opengles/GL11.java
index 943a5be..3ba110c 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL11.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL11.java
@@ -1,18 +1,19 @@
-/*
- * Copyright (C) 2006 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.
- */
+/* //device/java/android/javax/microedition/khronos/opengles/GL11.java
+**
+** Copyright 2006, 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.
+*/
 
 // This source file is automatically generated
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java b/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java
index 842db7a..459a1ab 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL11Ext.java
@@ -1,18 +1,19 @@
-/*
- * Copyright (C) 2007 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.
- */
+/* //device/java/android/javax/microedition/khronos/opengles/GL11Ext.java
+**
+** Copyright 2007, 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.
+*/
 
 // This source file is automatically generated
 
diff --git a/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java b/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
index 97d5fd8..933c91e 100644
--- a/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
+++ b/opengl/java/javax/microedition/khronos/opengles/GL11ExtensionPack.java
@@ -1,18 +1,19 @@
-/*
- * Copyright (C) 2007 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.
- */
+/* //device/java/android/javax/microedition/khronos/opengles/GL11ExtensionPack.java
+**
+** Copyright 2007, 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.
+*/
 
 // This source file is automatically generated
 
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 6c1a231..31f4190 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -21,7 +21,7 @@
 echo "package android.graphics;" > out/android/graphics/Canvas.java
 echo "public interface Canvas {}" >> out/android/graphics/Canvas.java
 
-echo "package android.app; import android.content.pm.IPackageManager; public class ActivityThread { public static final ActivityThread currentActivityThread() { return null; } public static final String currentPackageName(){ return null; } public static IPackageManager getPackageManager() { return null;} }" > out/android/app/ActivityThread.java
+echo "package android.app; import android.content.pm.IPackageManager; public class AppGlobals { public static IPackageManager getPackageManager() { return null;} }" > out/android/app/AppGlobals.java
 # echo "package android.content; import android.content.pm.PackageManager; public interface Context { public PackageManager getPackageManager(); }" > out/android/content/Context.java
 echo "package android.content.pm; public class ApplicationInfo {public int targetSdkVersion;}" > out/android/content/pm/ApplicationInfo.java
 echo "package android.content.pm; public interface IPackageManager {ApplicationInfo getApplicationInfo(java.lang.String packageName, int flags) throws android.os.RemoteException;}" > out/android/content/pm/IPackageManager.java
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 9d8c5a0..9fa2b74 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -58,7 +58,7 @@
         } else if (baseType.equals("void")) {
             // nothing.
         } else {
-            throw new RuntimeException("Uknown primitive basetype " + baseType);
+            throw new RuntimeException("Unknown primitive basetype " + baseType);
         }
         return jniName;
     }
@@ -200,15 +200,9 @@
                 if (emitExceptionCheck) {
                     out.println(iii + indent + "_exception = 1;");
                 }
-                out.println(iii + indent +
-                            (mUseCPlusPlus ? "_env" : "(*_env)") +
-                            "->ThrowNew(" +
-                            (mUseCPlusPlus ? "" : "_env, ") +
-                            "IAEClass, " +
-                            "\"" +
-                            (isBuffer ?
-                             "remaining()" : "length - " + offset) +
-                            " < needed\");");
+                out.println(iii + indent + "jniThrowException(_env, " +
+                        "\"java/lang/IllegalArgumentException\", " +
+                        "\"" + (isBuffer ? "remaining()" : "length - " + offset) + " < needed\");");
                 out.println(iii + indent + "goto exit;");
                 needsExit = true;
                 out.println(iii + "}");
@@ -302,7 +296,7 @@
         }
         return false;
     }
-    
+
     String isRequiresFunc(CFunc cfunc) {
         String[] checks = mChecker.getChecks(cfunc.getName());
         int index = 1;
@@ -329,109 +323,94 @@
         }
         return null;
     }
-    
+
     void emitNativeBoundsChecks(CFunc cfunc, String cname, PrintStream out,
             boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
 
-                String[] checks = mChecker.getChecks(cfunc.getName());
+        String[] checks = mChecker.getChecks(cfunc.getName());
 
-                boolean lastWasIfcheck = false;
+        boolean lastWasIfcheck = false;
 
-                int index = 1;
-                if (checks != null) {
-                    while (index < checks.length) {
-                        if (checks[index].startsWith("check")) {
-                            if (lastWasIfcheck) {
-                                printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
-                                                      offset, remaining, iii);
-                            }
-                            lastWasIfcheck = false;
-                            if (cname != null && !cname.equals(checks[index + 1])) {
-                                index += 3;
-                                continue;
-                            }
-                            out.println(iii + "if (" + remaining + " < " +
-                                        checks[index + 2] +
-                                        ") {");
-                            if (emitExceptionCheck) {
-                                out.println(iii + indent + "_exception = 1;");
-                            }
-                    String exceptionClassName = "IAEClass";
+        int index = 1;
+        if (checks != null) {
+            while (index < checks.length) {
+                if (checks[index].startsWith("check")) {
+                    if (lastWasIfcheck) {
+                        printIfcheckPostamble(out, isBuffer, emitExceptionCheck,
+                                offset, remaining, iii);
+                    }
+                    lastWasIfcheck = false;
+                    if (cname != null && !cname.equals(checks[index + 1])) {
+                        index += 3;
+                        continue;
+                    }
+                    out.println(iii + "if (" + remaining + " < " + checks[index + 2] + ") {");
+                    if (emitExceptionCheck) {
+                        out.println(iii + indent + "_exception = 1;");
+                    }
+                    String exceptionClassName = "java/lang/IllegalArgumentException";
                     // If the "check" keyword was of the form
                     // "check_<class name>", use the class name in the
                     // exception to be thrown
                     int underscore = checks[index].indexOf('_');
                     if (underscore >= 0) {
-                    exceptionClassName = checks[index].substring(underscore + 1) + "Class";
-                    }
-                            out.println(iii + indent +
-                                        (mUseCPlusPlus ? "_env" : "(*_env)") +
-                                        "->ThrowNew(" +
-                                        (mUseCPlusPlus ? "" : "_env, ") +
-                        exceptionClassName + ", " +
-                                        "\"" +
-                                        (isBuffer ?
-                                         "remaining()" : "length - " + offset) +
-                                        " < " + checks[index + 2] +
-                                        "\");");
-
-                            out.println(iii + indent + "goto exit;");
-                            needsExit = true;
-                            out.println(iii + "}");
-
-                            index += 3;
-                        } else if (checks[index].equals("ifcheck")) {
-                            String[] matches = checks[index + 4].split(",");
-
-                            if (!lastWasIfcheck) {
-                                out.println(iii + "int _needed;");
-                                out.println(iii +
-                                            "switch (" +
-                                            checks[index + 3] +
-                                            ") {");
-                            }
-
-                            for (int i = 0; i < matches.length; i++) {
-                                out.println("#if defined(" + matches[i] + ")");
-                                out.println(iii +
-                                            "    case " +
-                                            matches[i] +
-                                            ":");
-                                out.println("#endif // defined(" + matches[i] + ")");
-                            }
-                            out.println(iii +
-                                        "        _needed = " +
-                                        checks[index + 2] +
-                                        ";");
-                            out.println(iii +
-                                        "        break;");
-
-                            lastWasIfcheck = true;
-                            index += 5;
-                        } else if (checks[index].equals("return")) {
-                            // ignore
-                            index += 2;
-                        } else if (checks[index].equals("unsupported")) {
-                            // ignore
-                            index += 1;
-                        } else if (checks[index].equals("requires")) {
-                            // ignore
-                            index += 2;
-                        } else if (checks[index].equals("nullAllowed")) {
-                            // ignore
-                            index += 1;
+                        String abbr = checks[index].substring(underscore + 1);
+                        if (abbr.equals("AIOOBE")) {
+                            exceptionClassName = "java/lang/ArrayIndexOutOfBoundsException";
                         } else {
-                            System.out.println("Error: unknown keyword \"" +
-                                               checks[index] + "\"");
-                            System.exit(0);
+                            throw new RuntimeException("unknown exception abbreviation: " + abbr);
                         }
                     }
-                }
+                    out.println(iii + indent + "jniThrowException(_env, " +
+                            "\"" + exceptionClassName + "\", " +
+                            "\"" + (isBuffer ? "remaining()" : "length - " + offset) + " < " + checks[index + 2] + "\");");
 
-                if (lastWasIfcheck) {
-                    printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
+                    out.println(iii + indent + "goto exit;");
+                    needsExit = true;
+                    out.println(iii + "}");
+
+                    index += 3;
+                } else if (checks[index].equals("ifcheck")) {
+                    String[] matches = checks[index + 4].split(",");
+
+                    if (!lastWasIfcheck) {
+                        out.println(iii + "int _needed;");
+                        out.println(iii + "switch (" + checks[index + 3] + ") {");
+                    }
+
+                    for (int i = 0; i < matches.length; i++) {
+                        out.println("#if defined(" + matches[i] + ")");
+                        out.println(iii + "    case " + matches[i] + ":");
+                        out.println("#endif // defined(" + matches[i] + ")");
+                    }
+                    out.println(iii + "        _needed = " + checks[index + 2] + ";");
+                    out.println(iii + "        break;");
+
+                    lastWasIfcheck = true;
+                    index += 5;
+                } else if (checks[index].equals("return")) {
+                    // ignore
+                    index += 2;
+                } else if (checks[index].equals("unsupported")) {
+                    // ignore
+                    index += 1;
+                } else if (checks[index].equals("requires")) {
+                    // ignore
+                    index += 2;
+                } else if (checks[index].equals("nullAllowed")) {
+                    // ignore
+                    index += 1;
+                } else {
+                    System.out.println("Error: unknown keyword \"" + checks[index] + "\"");
+                    System.exit(0);
                 }
             }
+        }
+
+        if (lastWasIfcheck) {
+            printIfcheckPostamble(out, isBuffer, emitExceptionCheck, iii);
+        }
+    }
 
     boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
         if (nonPrimitiveArgs.size() > 0) {
@@ -817,7 +796,7 @@
         boolean isUnsupported = isUnsupportedFunc(cfunc);
         if (isUnsupported) {
             out.println(indent +
-                        "_env->ThrowNew(UOEClass,");
+                        "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
             out.println(indent +
                         "    \"" + cfunc.getName() + "\");");
             if (!isVoid) {
@@ -828,13 +807,13 @@
             out.println();
             return;
         }
-        
+
         String requiresExtension = isRequiresFunc(cfunc);
         if (requiresExtension != null) {
             out.println(indent +
                         "if (! supportsExtension(_env, _this, have_" + requiresExtension + "ID)) {");
             out.println(indent + indent +
-                        "_env->ThrowNew(UOEClass,");
+                        "jniThrowException(_env, \"java/lang/UnsupportedOperationException\",");
             out.println(indent + indent +
                         "    \"" + cfunc.getName() + "\");");
             if (isVoid) {
@@ -945,7 +924,8 @@
                 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
                 String decl = type.getDeclaration();
                 out.println(indent + "if (!" + cname + ") {");
-                out.println(indent + "    _env->ThrowNew(IAEClass, \"" + cname + " == null\");");
+                out.println(indent + "    jniThrowException(_env, " +
+                        "\"java/lang/IllegalArgumentException\", \"" + cname + " == null\");");
                 out.println(indent + "    goto exit;");
                 needsExit = true;
                 out.println(indent + "}");
@@ -978,13 +958,9 @@
                     if (emitExceptionCheck) {
                         out.println(indent + indent + "_exception = 1;");
                     }
-                    out.println(indent + "    " +
-                                (mUseCPlusPlus ? "_env" : "(*_env)") +
-                                "->ThrowNew(" +
-                                (mUseCPlusPlus ? "" : "_env, ") +
-                                "IAEClass, " +
-                                "\"" + cname +
-                                " == null\");");
+                    out.println(indent + "    jniThrowException(_env, " +
+                            "\"java/lang/IllegalArgumentException\", " +
+                            "\"" + cname + " == null\");");
                     out.println(indent + "    goto exit;");
                     needsExit = true;
                     out.println(indent + "}");
@@ -993,12 +969,8 @@
                     if (emitExceptionCheck) {
                         out.println(indent + indent + "_exception = 1;");
                     }
-                    out.println(indent + "    " +
-                                (mUseCPlusPlus ? "_env" : "(*_env)") +
-                                "->ThrowNew(" +
-                                (mUseCPlusPlus ? "" : "_env, ") +
-                                "IAEClass, " +
-                                "\"" + offset + " < 0\");");
+                    out.println(indent + "    jniThrowException(_env, " +
+                            "\"java/lang/IllegalArgumentException\", \"" + offset + " < 0\");");
                     out.println(indent + "    goto exit;");
                     needsExit = true;
                     out.println(indent + "}");
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
index 294d1ce..5d418d7 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10ExtcHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2009, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -27,10 +29,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -41,7 +39,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -63,26 +61,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -103,13 +81,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -122,4 +100,3 @@
 }
 
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
index e1c09f4..35a3c33 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES10cHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2009, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -40,10 +42,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -54,7 +52,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -75,26 +73,6 @@
         _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
 }
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -115,13 +93,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -140,7 +118,8 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
@@ -153,4 +132,3 @@
 }
 
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
index 2548b32..9b29a44 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11ExtcHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2009, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -36,10 +38,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -50,7 +48,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -72,26 +70,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -112,13 +90,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -138,9 +116,9 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
index 4c297f7..823079f 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES11cHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2009, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -34,10 +36,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -48,7 +46,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -70,26 +68,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -110,13 +88,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -136,10 +114,10 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
 
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
index e451e9a..13a2577 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
+++ b/opengl/tools/glgen/stubs/gles11/GLES20cHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2009, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -27,10 +29,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
 static jmethodID getBaseArrayOffsetID;
@@ -41,7 +39,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -63,26 +61,6 @@
 }
 
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -103,13 +81,13 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -129,7 +107,8 @@
         jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
         buf += position << elementSizeShift;
     } else {
-        _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
     }
     return (void*) buf;
 }
@@ -147,4 +126,3 @@
 }
 
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/gles11/glGetProgramInfoLog.cpp b/opengl/tools/glgen/stubs/gles11/glGetProgramInfoLog.cpp
index d92f5159..ce6ab24 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetProgramInfoLog.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetProgramInfoLog.cpp
@@ -1,27 +1,19 @@
-#include <string.h>
+#include <stdlib.h>
 
 /* void glGetProgramInfoLog ( GLuint shader, GLsizei maxLength, GLsizei* length, GLchar* infoLog ) */
-static
-jstring
-android_glGetProgramInfoLog (JNIEnv *_env, jobject _this, jint shader) {
+static jstring android_glGetProgramInfoLog(JNIEnv *_env, jobject, jint shader) {
     GLint infoLen = 0;
-    jstring _result = 0;
-    char* buf = 0;
     glGetProgramiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
-    if (infoLen) {
-        char* buf = (char*) malloc(infoLen);
-        if (buf == 0) {
-            _env->ThrowNew(IAEClass, "out of memory");
-            goto exit;
-        }
-        glGetProgramInfoLog(shader, infoLen, NULL, buf);
-        _result = _env->NewStringUTF(buf);
-    } else {
-        _result = _env->NewStringUTF("");
+    if (!infoLen) {
+        return _env->NewStringUTF("");
     }
-exit:
-    if (buf) {
-            free(buf);
+    char* buf = (char*) malloc(infoLen);
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
     }
-    return _result;
-}
\ No newline at end of file
+    glGetProgramInfoLog(shader, infoLen, NULL, buf);
+    jstring result = _env->NewStringUTF(buf);
+    free(buf);
+    return result;
+}
diff --git a/opengl/tools/glgen/stubs/gles11/glGetShaderInfoLog.cpp b/opengl/tools/glgen/stubs/gles11/glGetShaderInfoLog.cpp
index 5441d66..dd656b6 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetShaderInfoLog.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetShaderInfoLog.cpp
@@ -1,27 +1,19 @@
-#include <string.h>
+#include <stdlib.h>
 
 /* void glGetShaderInfoLog ( GLuint shader, GLsizei maxLength, GLsizei* length, GLchar* infoLog ) */
-static
-jstring
-android_glGetShaderInfoLog (JNIEnv *_env, jobject _this, jint shader) {
+static jstring android_glGetShaderInfoLog(JNIEnv *_env, jobject, jint shader) {
     GLint infoLen = 0;
-    jstring _result = 0;
-    char* buf = 0;
     glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
-    if (infoLen) {
-        char* buf = (char*) malloc(infoLen);
-        if (buf == 0) {
-            _env->ThrowNew(IAEClass, "out of memory");
-            goto exit;
-        }
-        glGetShaderInfoLog(shader, infoLen, NULL, buf);
-        _result = _env->NewStringUTF(buf);
-    } else {
-        _result = _env->NewStringUTF("");
+    if (!infoLen) {
+        return _env->NewStringUTF("");
     }
-exit:
-    if (buf) {
-            free(buf);
+    char* buf = (char*) malloc(infoLen);
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "out of memory");
+        return NULL;
     }
-    return _result;
-}
\ No newline at end of file
+    glGetShaderInfoLog(shader, infoLen, NULL, buf);
+    jstring result = _env->NewStringUTF(buf);
+    free(buf);
+    return result;
+}
diff --git a/opengl/tools/glgen/stubs/gles11/glGetString.cpp b/opengl/tools/glgen/stubs/gles11/glGetString.cpp
index a400859..239fe4a 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetString.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetString.cpp
@@ -1,11 +1,5 @@
-#include <string.h>

-

 /* const GLubyte * glGetString ( GLenum name ) */

-static

-jstring

-android_glGetString

-  (JNIEnv *_env, jobject _this, jint name) {

-    const char * chars = (const char *)glGetString((GLenum)name);

-    jstring output = _env->NewStringUTF(chars);

-    return output;

+static jstring android_glGetString(JNIEnv* _env, jobject, jint name) {

+    const char* chars = (const char*) glGetString((GLenum) name);

+    return _env->NewStringUTF(chars);

 }

diff --git a/opengl/tools/glgen/stubs/gles11/glShaderSource.cpp b/opengl/tools/glgen/stubs/gles11/glShaderSource.cpp
index c274108..125fd0f 100644
--- a/opengl/tools/glgen/stubs/gles11/glShaderSource.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glShaderSource.cpp
@@ -6,7 +6,7 @@
     (JNIEnv *_env, jobject _this, jint shader, jstring string) {
 
     if (!string) {
-        _env->ThrowNew(IAEClass, "string == null");
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "string == null");
         return;
     }
 
diff --git a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
index c2464b0..f7315ee 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/GLCHeader.cpp
@@ -1,21 +1,23 @@
 **
 ** Copyright 2006, 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 
+** 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 
+**     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 
+** 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.
 */
 
 // This source file is automatically generated
 
+#include "jni.h"
+#include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 
@@ -63,10 +65,6 @@
 
 static jclass nioAccessClass;
 static jclass bufferClass;
-static jclass OOMEClass;
-static jclass UOEClass;
-static jclass IAEClass;
-static jclass AIOOBEClass;
 static jclass G11ImplClass;
 static jmethodID getBasePointerID;
 static jmethodID getBaseArrayID;
@@ -84,7 +82,7 @@
 /* Cache method IDs each time the class is loaded. */
 
 static void
-nativeClassInitBuffer(JNIEnv *_env)
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
 {
     jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
     nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
@@ -114,26 +112,6 @@
         _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
 }
 
-static void
-nativeClassInit(JNIEnv *_env, jclass glImplClass)
-{
-    nativeClassInitBuffer(_env);
-
-    jclass IAEClassLocal =
-        _env->FindClass("java/lang/IllegalArgumentException");
-    jclass OOMEClassLocal =
-         _env->FindClass("java/lang/OutOfMemoryError");
-    jclass UOEClassLocal =
-         _env->FindClass("java/lang/UnsupportedOperationException");
-    jclass AIOOBEClassLocal =
-         _env->FindClass("java/lang/ArrayIndexOutOfBoundsException");
-
-    IAEClass = (jclass) _env->NewGlobalRef(IAEClassLocal);
-    OOMEClass = (jclass) _env->NewGlobalRef(OOMEClassLocal);
-    UOEClass = (jclass) _env->NewGlobalRef(UOEClassLocal);
-    AIOOBEClass = (jclass) _env->NewGlobalRef(AIOOBEClassLocal);
-}
-
 static void *
 getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining)
 {
@@ -154,7 +132,7 @@
         *array = NULL;
         return (void *) (jint) pointer;
     }
-    
+
     *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
             getBaseArrayID, buffer);
     if (*array == NULL) {
@@ -163,7 +141,7 @@
     offset = _env->CallStaticIntMethod(nioAccessClass,
             getBaseArrayOffsetID, buffer);
     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *) 0);
-    
+
     return (void *) ((char *) data + offset);
 }
 
@@ -207,7 +185,8 @@
                 releasePointer(_env, array, buf, 0);
             }
         } else {
-            _env->ThrowNew(IAEClass, "Must use a native order direct Buffer");
+            jniThrowException(_env, "java/lang/IllegalArgumentException",
+                              "Must use a native order direct Buffer");
         }
     }
     return buf;
@@ -250,7 +229,7 @@
         }
     }
 }
-    
+
 static bool
 checkForExtension(const GLubyte* pExtensions, const GLubyte* pExtension) {
     for (;*pExtensions != '\0'; pExtensions = nextExtension(pExtensions)) {
@@ -279,4 +258,3 @@
 }
 
 // --------------------------------------------------------------------------
-
diff --git a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
index 3727106..cd730aa 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
+++ b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
@@ -18,7 +18,7 @@
 
 package com.google.android.gles_jni;
 
-import android.app.ActivityThread;
+import android.app.AppGlobals;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.os.Build;
@@ -64,7 +64,7 @@
     private static boolean allowIndirectBuffers(String appName) {
         boolean result = false;
         int version = 0;
-        IPackageManager pm = ActivityThread.getPackageManager();
+        IPackageManager pm = AppGlobals.getPackageManager();
         try {
             ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0);
             if (applicationInfo != null) {
diff --git a/opengl/tools/glgen/stubs/jsr239/glGetString.cpp b/opengl/tools/glgen/stubs/jsr239/glGetString.cpp
index a400859..cd6e3f3 100644
--- a/opengl/tools/glgen/stubs/jsr239/glGetString.cpp
+++ b/opengl/tools/glgen/stubs/jsr239/glGetString.cpp
@@ -1,11 +1,5 @@
-#include <string.h>

-

 /* const GLubyte * glGetString ( GLenum name ) */

-static

-jstring

-android_glGetString

-  (JNIEnv *_env, jobject _this, jint name) {

-    const char * chars = (const char *)glGetString((GLenum)name);

-    jstring output = _env->NewStringUTF(chars);

-    return output;

+static jstring android_glGetString(JNIEnv *_env, jobject, jint name) {

+    const char* chars = (const char*) glGetString((GLenum) name);

+    return _env->NewStringUTF(chars);

 }

diff --git a/services/audioflinger/AudioResampler.cpp b/services/audioflinger/AudioResampler.cpp
index 5c3b43fc..dca795c 100644
--- a/services/audioflinger/AudioResampler.cpp
+++ b/services/audioflinger/AudioResampler.cpp
@@ -26,11 +26,15 @@
 #include "AudioResamplerSinc.h"
 #include "AudioResamplerCubic.h"
 
+#ifdef __arm__
+#include <machine/cpu-features.h>
+#endif
+
 namespace android {
 
-#ifdef __ARM_ARCH_5E__  // optimized asm option
+#ifdef __ARM_HAVE_HALFWORD_MULTIPLY // optimized asm option
     #define ASM_ARM_RESAMP1 // enable asm optimisation for ResamplerOrder1
-#endif // __ARM_ARCH_5E__
+#endif // __ARM_HAVE_HALFWORD_MULTIPLY
 // ----------------------------------------------------------------------------
 
 class AudioResamplerOrder1 : public AudioResampler {
diff --git a/services/input/Android.mk b/services/input/Android.mk
index 96431bc..f9f8623 100644
--- a/services/input/Android.mk
+++ b/services/input/Android.mk
@@ -22,7 +22,9 @@
     InputManager.cpp \
     InputReader.cpp \
     InputWindow.cpp \
-    PointerController.cpp
+    PointerController.cpp \
+    SpotController.cpp \
+    SpriteController.cpp
 
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index cf9b13d..9ed1391 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -20,6 +20,7 @@
 #include "EventHub.h"
 #include "InputDispatcher.h"
 #include "PointerController.h"
+#include "SpotController.h"
 
 #include <ui/Input.h>
 #include <ui/DisplayInfo.h>
@@ -89,6 +90,9 @@
 
     /* Gets a pointer controller associated with the specified cursor device (ie. a mouse). */
     virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) = 0;
+
+    /* Gets a spot controller associated with the specified touch pad device. */
+    virtual sp<SpotControllerInterface> obtainSpotController(int32_t deviceId) = 0;
 };
 
 
diff --git a/services/input/PointerController.cpp b/services/input/PointerController.cpp
index a4ee295..15effb7 100644
--- a/services/input/PointerController.cpp
+++ b/services/input/PointerController.cpp
@@ -49,8 +49,11 @@
 static const float FADE_DECAY_PER_FRAME = float(FADE_FRAME_INTERVAL) / FADE_DURATION;
 
 
-PointerController::PointerController(const sp<Looper>& looper, int32_t pointerLayer) :
-        mLooper(looper), mPointerLayer(pointerLayer) {
+PointerController::PointerController(const sp<Looper>& looper,
+        const sp<SpriteController>& spriteController) :
+        mLooper(looper), mSpriteController(spriteController) {
+    mHandler = new WeakMessageHandler(this);
+
     AutoMutex _l(mLock);
 
     mLocked.displayWidth = -1;
@@ -61,34 +64,20 @@
     mLocked.pointerY = 0;
     mLocked.buttonState = 0;
 
-    mLocked.iconBitmap = NULL;
-    mLocked.iconHotSpotX = 0;
-    mLocked.iconHotSpotY = 0;
-
     mLocked.fadeAlpha = 1;
     mLocked.inactivityFadeDelay = INACTIVITY_FADE_DELAY_NORMAL;
 
-    mLocked.wantVisible = false;
     mLocked.visible = false;
-    mLocked.drawn = false;
 
-    mHandler = new WeakMessageHandler(this);
+    mLocked.sprite = mSpriteController->createSprite();
 }
 
 PointerController::~PointerController() {
     mLooper->removeMessages(mHandler);
 
-    if (mSurfaceControl != NULL) {
-        mSurfaceControl->clear();
-        mSurfaceControl.clear();
-    }
+    AutoMutex _l(mLock);
 
-    if (mSurfaceComposerClient != NULL) {
-        mSurfaceComposerClient->dispose();
-        mSurfaceComposerClient.clear();
-    }
-
-    delete mLocked.iconBitmap;
+    mLocked.sprite.clear();
 }
 
 bool PointerController::getBounds(float* outMinX, float* outMinY,
@@ -214,75 +203,11 @@
 }
 
 void PointerController::updateLocked() {
-    bool wantVisibleAndHavePointerIcon = mLocked.wantVisible && mLocked.iconBitmap;
-
-    if (wantVisibleAndHavePointerIcon) {
-        // Want the pointer to be visible.
-        // Ensure the surface is created and drawn.
-        if (!createSurfaceIfNeededLocked() || !drawPointerIfNeededLocked()) {
-            return;
-        }
-    } else {
-        // Don't want the pointer to be visible.
-        // If it is not visible then we are done.
-        if (mSurfaceControl == NULL || !mLocked.visible) {
-            return;
-        }
-    }
-
-    status_t status = mSurfaceComposerClient->openTransaction();
-    if (status) {
-        LOGE("Error opening surface transaction to update pointer surface.");
-        return;
-    }
-
-    if (wantVisibleAndHavePointerIcon) {
-        status = mSurfaceControl->setPosition(
-                mLocked.pointerX - mLocked.iconHotSpotX,
-                mLocked.pointerY - mLocked.iconHotSpotY);
-        if (status) {
-            LOGE("Error %d moving pointer surface.", status);
-            goto CloseTransaction;
-        }
-
-        status = mSurfaceControl->setAlpha(mLocked.fadeAlpha);
-        if (status) {
-            LOGE("Error %d setting pointer surface alpha.", status);
-            goto CloseTransaction;
-        }
-
-        if (!mLocked.visible) {
-            status = mSurfaceControl->setLayer(mPointerLayer);
-            if (status) {
-                LOGE("Error %d setting pointer surface layer.", status);
-                goto CloseTransaction;
-            }
-
-            status = mSurfaceControl->show(mPointerLayer);
-            if (status) {
-                LOGE("Error %d showing pointer surface.", status);
-                goto CloseTransaction;
-            }
-
-            mLocked.visible = true;
-        }
-    } else {
-        if (mLocked.visible) {
-            status = mSurfaceControl->hide();
-            if (status) {
-                LOGE("Error %d hiding pointer surface.", status);
-                goto CloseTransaction;
-            }
-
-            mLocked.visible = false;
-        }
-    }
-
-CloseTransaction:
-    status = mSurfaceComposerClient->closeTransaction();
-    if (status) {
-        LOGE("Error closing surface transaction to update pointer surface.");
-    }
+    mLocked.sprite->openTransaction();
+    mLocked.sprite->setPosition(mLocked.pointerX, mLocked.pointerY);
+    mLocked.sprite->setAlpha(mLocked.fadeAlpha);
+    mLocked.sprite->setVisible(mLocked.visible);
+    mLocked.sprite->closeTransaction();
 }
 
 void PointerController::setDisplaySize(int32_t width, int32_t height) {
@@ -339,7 +264,7 @@
         case DISPLAY_ORIENTATION_90:
             temp = x;
             x = y;
-            y = mLocked.displayWidth - x;
+            y = mLocked.displayWidth - temp;
             break;
         case DISPLAY_ORIENTATION_180:
             x = mLocked.displayWidth - x;
@@ -365,106 +290,7 @@
 void PointerController::setPointerIcon(const SkBitmap* bitmap, float hotSpotX, float hotSpotY) {
     AutoMutex _l(mLock);
 
-    if (mLocked.iconBitmap) {
-        delete mLocked.iconBitmap;
-        mLocked.iconBitmap = NULL;
-    }
-
-    if (bitmap) {
-        mLocked.iconBitmap = new SkBitmap();
-        bitmap->copyTo(mLocked.iconBitmap, SkBitmap::kARGB_8888_Config);
-    }
-
-    mLocked.iconHotSpotX = hotSpotX;
-    mLocked.iconHotSpotY = hotSpotY;
-    mLocked.drawn = false;
-}
-
-bool PointerController::createSurfaceIfNeededLocked() {
-    if (!mLocked.iconBitmap) {
-        // If we don't have a pointer icon, then no point allocating a surface now.
-        return false;
-    }
-
-    if (mSurfaceComposerClient == NULL) {
-        mSurfaceComposerClient = new SurfaceComposerClient();
-    }
-
-    if (mSurfaceControl == NULL) {
-        mSurfaceControl = mSurfaceComposerClient->createSurface(getpid(),
-                String8("Pointer Icon"), 0,
-                mLocked.iconBitmap->width(), mLocked.iconBitmap->height(),
-                PIXEL_FORMAT_RGBA_8888);
-        if (mSurfaceControl == NULL) {
-            LOGE("Error creating pointer surface.");
-            return false;
-        }
-    }
-    return true;
-}
-
-bool PointerController::drawPointerIfNeededLocked() {
-    if (!mLocked.drawn) {
-        if (!mLocked.iconBitmap) {
-            return false;
-        }
-
-        if (!resizeSurfaceLocked(mLocked.iconBitmap->width(), mLocked.iconBitmap->height())) {
-            return false;
-        }
-
-        sp<Surface> surface = mSurfaceControl->getSurface();
-
-        Surface::SurfaceInfo surfaceInfo;
-        status_t status = surface->lock(&surfaceInfo);
-        if (status) {
-            LOGE("Error %d locking pointer surface before drawing.", status);
-            return false;
-        }
-
-        SkBitmap surfaceBitmap;
-        ssize_t bpr = surfaceInfo.s * bytesPerPixel(surfaceInfo.format);
-        surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config, surfaceInfo.w, surfaceInfo.h, bpr);
-        surfaceBitmap.setPixels(surfaceInfo.bits);
-
-        SkCanvas surfaceCanvas;
-        surfaceCanvas.setBitmapDevice(surfaceBitmap);
-
-        SkPaint paint;
-        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
-        surfaceCanvas.drawBitmap(*mLocked.iconBitmap, 0, 0, &paint);
-
-        status = surface->unlockAndPost();
-        if (status) {
-            LOGE("Error %d unlocking pointer surface after drawing.", status);
-            return false;
-        }
-    }
-
-    mLocked.drawn = true;
-    return true;
-}
-
-bool PointerController::resizeSurfaceLocked(int32_t width, int32_t height) {
-    status_t status = mSurfaceComposerClient->openTransaction();
-    if (status) {
-        LOGE("Error opening surface transaction to resize pointer surface.");
-        return false;
-    }
-
-    status = mSurfaceControl->setSize(width, height);
-    if (status) {
-        LOGE("Error %d setting pointer surface size.", status);
-        return false;
-    }
-
-    status = mSurfaceComposerClient->closeTransaction();
-    if (status) {
-        LOGE("Error closing surface transaction to resize pointer surface.");
-        return false;
-    }
-
-    return true;
+    mLocked.sprite->setBitmap(bitmap, hotSpotX, hotSpotY);
 }
 
 void PointerController::handleMessage(const Message& message) {
@@ -481,7 +307,7 @@
     sendFadeStepMessageDelayedLocked(getInactivityFadeDelayTimeLocked());
 
     if (isFadingLocked()) {
-        mLocked.wantVisible = true;
+        mLocked.visible = true;
         mLocked.fadeAlpha = 1;
         return true; // update required to effect the unfade
     }
@@ -501,11 +327,11 @@
 }
 
 void PointerController::fadeStepLocked() {
-    if (mLocked.wantVisible) {
+    if (mLocked.visible) {
         mLocked.fadeAlpha -= FADE_DECAY_PER_FRAME;
         if (mLocked.fadeAlpha < 0) {
             mLocked.fadeAlpha = 0;
-            mLocked.wantVisible = false;
+            mLocked.visible = false;
         } else {
             sendFadeStepMessageDelayedLocked(FADE_FRAME_INTERVAL);
         }
@@ -514,7 +340,7 @@
 }
 
 bool PointerController::isFadingLocked() {
-    return !mLocked.wantVisible || mLocked.fadeAlpha != 1;
+    return !mLocked.visible || mLocked.fadeAlpha != 1;
 }
 
 nsecs_t PointerController::getInactivityFadeDelayTimeLocked() {
diff --git a/services/input/PointerController.h b/services/input/PointerController.h
index e1dab5c..d467a5a 100644
--- a/services/input/PointerController.h
+++ b/services/input/PointerController.h
@@ -17,16 +17,14 @@
 #ifndef _UI_POINTER_CONTROLLER_H
 #define _UI_POINTER_CONTROLLER_H
 
+#include "SpriteController.h"
+
 #include <ui/DisplayInfo.h>
 #include <ui/Input.h>
 #include <utils/RefBase.h>
 #include <utils/Looper.h>
 #include <utils/String8.h>
 
-#include <surfaceflinger/Surface.h>
-#include <surfaceflinger/SurfaceComposerClient.h>
-#include <surfaceflinger/ISurfaceComposer.h>
-
 #include <SkBitmap.h>
 
 namespace android {
@@ -86,7 +84,7 @@
         INACTIVITY_FADE_DELAY_SHORT = 1,
     };
 
-    PointerController(const sp<Looper>& looper, int32_t pointerLayer);
+    PointerController(const sp<Looper>& looper, const sp<SpriteController>& spriteController);
 
     virtual bool getBounds(float* outMinX, float* outMinY,
             float* outMaxX, float* outMaxY) const;
@@ -111,9 +109,8 @@
     mutable Mutex mLock;
 
     sp<Looper> mLooper;
-    int32_t mPointerLayer;
-    sp<SurfaceComposerClient> mSurfaceComposerClient;
-    sp<SurfaceControl> mSurfaceControl;
+    sp<SpriteController> mSpriteController;
+    sp<WeakMessageHandler> mHandler;
 
     struct Locked {
         int32_t displayWidth;
@@ -124,26 +121,17 @@
         float pointerY;
         uint32_t buttonState;
 
-        SkBitmap* iconBitmap;
-        float iconHotSpotX;
-        float iconHotSpotY;
-
         float fadeAlpha;
         InactivityFadeDelay inactivityFadeDelay;
 
-        bool wantVisible;
         bool visible;
-        bool drawn;
-    } mLocked;
 
-    sp<WeakMessageHandler> mHandler;
+        sp<Sprite> sprite;
+    } mLocked;
 
     bool getBoundsLocked(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
     void setPositionLocked(float x, float y);
     void updateLocked();
-    bool createSurfaceIfNeededLocked();
-    bool drawPointerIfNeededLocked();
-    bool resizeSurfaceLocked(int32_t width, int32_t height);
 
     void handleMessage(const Message& message);
     bool unfadeBeforeUpdateLocked();
diff --git a/services/input/SpotController.cpp b/services/input/SpotController.cpp
new file mode 100644
index 0000000..dffad81
--- /dev/null
+++ b/services/input/SpotController.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "SpotController"
+
+//#define LOG_NDEBUG 0
+
+// Log debug messages about spot updates
+#define DEBUG_SPOT_UPDATES 0
+
+#include "SpotController.h"
+
+#include <cutils/log.h>
+
+namespace android {
+
+// --- SpotController ---
+
+SpotController::SpotController(const sp<Looper>& looper,
+        const sp<SpriteController>& spriteController) :
+        mLooper(looper), mSpriteController(spriteController) {
+    mHandler = new WeakMessageHandler(this);
+}
+
+SpotController::~SpotController() {
+    mLooper->removeMessages(mHandler);
+}
+
+void SpotController:: handleMessage(const Message& message) {
+}
+
+} // namespace android
diff --git a/services/input/SpotController.h b/services/input/SpotController.h
new file mode 100644
index 0000000..1d091d7
--- /dev/null
+++ b/services/input/SpotController.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_SPOT_CONTROLLER_H
+#define _UI_SPOT_CONTROLLER_H
+
+#include "SpriteController.h"
+
+#include <utils/RefBase.h>
+#include <utils/Looper.h>
+
+#include <SkBitmap.h>
+
+namespace android {
+
+/*
+ * Interface for displaying spots on screen that visually represent the positions
+ * of fingers on a touch pad.
+ *
+ * The spot controller is responsible for providing synchronization and for tracking
+ * display orientation changes if needed.
+ */
+class SpotControllerInterface : public virtual RefBase {
+protected:
+    SpotControllerInterface() { }
+    virtual ~SpotControllerInterface() { }
+
+public:
+
+};
+
+
+/*
+ * Sprite-based spot controller implementation.
+ */
+class SpotController : public SpotControllerInterface, public MessageHandler {
+protected:
+    virtual ~SpotController();
+
+public:
+    SpotController(const sp<Looper>& looper, const sp<SpriteController>& spriteController);
+
+private:
+    mutable Mutex mLock;
+
+    sp<Looper> mLooper;
+    sp<SpriteController> mSpriteController;
+    sp<WeakMessageHandler> mHandler;
+
+    struct Locked {
+    } mLocked;
+
+    void handleMessage(const Message& message);
+};
+
+} // namespace android
+
+#endif // _UI_SPOT_CONTROLLER_H
diff --git a/services/input/SpriteController.cpp b/services/input/SpriteController.cpp
new file mode 100644
index 0000000..c6d4390f
--- /dev/null
+++ b/services/input/SpriteController.cpp
@@ -0,0 +1,472 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Sprites"
+
+//#define LOG_NDEBUG 0
+
+#include "SpriteController.h"
+
+#include <cutils/log.h>
+#include <utils/String8.h>
+
+#include <SkBitmap.h>
+#include <SkCanvas.h>
+#include <SkColor.h>
+#include <SkPaint.h>
+#include <SkXfermode.h>
+
+namespace android {
+
+// --- SpriteController ---
+
+SpriteController::SpriteController(const sp<Looper>& looper, int32_t overlayLayer) :
+        mLooper(looper), mOverlayLayer(overlayLayer) {
+    mHandler = new WeakMessageHandler(this);
+}
+
+SpriteController::~SpriteController() {
+    mLooper->removeMessages(mHandler);
+
+    if (mSurfaceComposerClient != NULL) {
+        mSurfaceComposerClient->dispose();
+        mSurfaceComposerClient.clear();
+    }
+}
+
+sp<Sprite> SpriteController::createSprite() {
+    return new SpriteImpl(this);
+}
+
+void SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) {
+    bool wasEmpty = mInvalidatedSprites.isEmpty();
+    mInvalidatedSprites.push(sprite);
+    if (wasEmpty) {
+        mLooper->sendMessage(mHandler, Message(MSG_UPDATE_SPRITES));
+    }
+}
+
+void SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) {
+    bool wasEmpty = mDisposedSurfaces.isEmpty();
+    mDisposedSurfaces.push(surfaceControl);
+    if (wasEmpty) {
+        mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES));
+    }
+}
+
+void SpriteController::handleMessage(const Message& message) {
+    switch (message.what) {
+    case MSG_UPDATE_SPRITES:
+        doUpdateSprites();
+        break;
+    case MSG_DISPOSE_SURFACES:
+        doDisposeSurfaces();
+        break;
+    }
+}
+
+void SpriteController::doUpdateSprites() {
+    // Collect information about sprite updates.
+    // Each sprite update record includes a reference to its associated sprite so we can
+    // be certain the sprites will not be deleted while this function runs.  Sprites
+    // may invalidate themselves again during this time but we will handle those changes
+    // in the next iteration.
+    Vector<SpriteUpdate> updates;
+    size_t numSprites;
+    { // acquire lock
+        AutoMutex _l(mLock);
+
+        numSprites = mInvalidatedSprites.size();
+        for (size_t i = 0; i < numSprites; i++) {
+            const sp<SpriteImpl>& sprite = mInvalidatedSprites.itemAt(i);
+
+            updates.push(SpriteUpdate(sprite, sprite->getStateLocked()));
+            sprite->resetDirtyLocked();
+        }
+        mInvalidatedSprites.clear();
+    } // release lock
+
+    // Create missing surfaces.
+    bool surfaceChanged = false;
+    for (size_t i = 0; i < numSprites; i++) {
+        SpriteUpdate& update = updates.editItemAt(i);
+
+        if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) {
+            update.state.surfaceWidth = update.state.bitmap.width();
+            update.state.surfaceHeight = update.state.bitmap.height();
+            update.state.surfaceDrawn = false;
+            update.state.surfaceVisible = false;
+            update.state.surfaceControl = obtainSurface(
+                    update.state.surfaceWidth, update.state.surfaceHeight);
+            if (update.state.surfaceControl != NULL) {
+                update.surfaceChanged = surfaceChanged = true;
+            }
+        }
+    }
+
+    // Resize sprites if needed, inside a global transaction.
+    bool haveGlobalTransaction = false;
+    for (size_t i = 0; i < numSprites; i++) {
+        SpriteUpdate& update = updates.editItemAt(i);
+
+        if (update.state.surfaceControl != NULL && update.state.wantSurfaceVisible()) {
+            int32_t desiredWidth = update.state.bitmap.width();
+            int32_t desiredHeight = update.state.bitmap.height();
+            if (update.state.surfaceWidth < desiredWidth
+                    || update.state.surfaceHeight < desiredHeight) {
+                if (!haveGlobalTransaction) {
+                    SurfaceComposerClient::openGlobalTransaction();
+                    haveGlobalTransaction = true;
+                }
+
+                status_t status = update.state.surfaceControl->setSize(desiredWidth, desiredHeight);
+                if (status) {
+                    LOGE("Error %d resizing sprite surface from %dx%d to %dx%d",
+                            status, update.state.surfaceWidth, update.state.surfaceHeight,
+                            desiredWidth, desiredHeight);
+                } else {
+                    update.state.surfaceWidth = desiredWidth;
+                    update.state.surfaceHeight = desiredHeight;
+                    update.state.surfaceDrawn = false;
+                    update.surfaceChanged = surfaceChanged = true;
+
+                    if (update.state.surfaceVisible) {
+                        status = update.state.surfaceControl->hide();
+                        if (status) {
+                            LOGE("Error %d hiding sprite surface after resize.", status);
+                        } else {
+                            update.state.surfaceVisible = false;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    if (haveGlobalTransaction) {
+        SurfaceComposerClient::closeGlobalTransaction();
+    }
+
+    // Redraw sprites if needed.
+    for (size_t i = 0; i < numSprites; i++) {
+        SpriteUpdate& update = updates.editItemAt(i);
+
+        if ((update.state.dirty & DIRTY_BITMAP) && update.state.surfaceDrawn) {
+            update.state.surfaceDrawn = false;
+            update.surfaceChanged = surfaceChanged = true;
+        }
+
+        if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn
+                && update.state.wantSurfaceVisible()) {
+            sp<Surface> surface = update.state.surfaceControl->getSurface();
+            Surface::SurfaceInfo surfaceInfo;
+            status_t status = surface->lock(&surfaceInfo);
+            if (status) {
+                LOGE("Error %d locking sprite surface before drawing.", status);
+            } else {
+                SkBitmap surfaceBitmap;
+                ssize_t bpr = surfaceInfo.s * bytesPerPixel(surfaceInfo.format);
+                surfaceBitmap.setConfig(SkBitmap::kARGB_8888_Config,
+                        surfaceInfo.w, surfaceInfo.h, bpr);
+                surfaceBitmap.setPixels(surfaceInfo.bits);
+
+                SkCanvas surfaceCanvas;
+                surfaceCanvas.setBitmapDevice(surfaceBitmap);
+
+                SkPaint paint;
+                paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+                surfaceCanvas.drawBitmap(update.state.bitmap, 0, 0, &paint);
+
+                if (surfaceInfo.w > uint32_t(update.state.bitmap.width())) {
+                    paint.setColor(0); // transparent fill color
+                    surfaceCanvas.drawRectCoords(update.state.bitmap.width(), 0,
+                            surfaceInfo.w, update.state.bitmap.height(), paint);
+                }
+                if (surfaceInfo.h > uint32_t(update.state.bitmap.height())) {
+                    paint.setColor(0); // transparent fill color
+                    surfaceCanvas.drawRectCoords(0, update.state.bitmap.height(),
+                            surfaceInfo.w, surfaceInfo.h, paint);
+                }
+
+                status = surface->unlockAndPost();
+                if (status) {
+                    LOGE("Error %d unlocking and posting sprite surface after drawing.", status);
+                } else {
+                    update.state.surfaceDrawn = true;
+                    update.surfaceChanged = surfaceChanged = true;
+                }
+            }
+        }
+    }
+
+    // Set sprite surface properties and make them visible.
+    bool haveTransaction = false;
+    for (size_t i = 0; i < numSprites; i++) {
+        SpriteUpdate& update = updates.editItemAt(i);
+
+        bool wantSurfaceVisibleAndDrawn = update.state.wantSurfaceVisible()
+                && update.state.surfaceDrawn;
+        bool becomingVisible = wantSurfaceVisibleAndDrawn && !update.state.surfaceVisible;
+        bool becomingHidden = !wantSurfaceVisibleAndDrawn && update.state.surfaceVisible;
+        if (update.state.surfaceControl != NULL && (becomingVisible || becomingHidden
+                || (wantSurfaceVisibleAndDrawn && (update.state.dirty & (DIRTY_ALPHA
+                        | DIRTY_POSITION | DIRTY_TRANSFORMATION_MATRIX | DIRTY_LAYER
+                        | DIRTY_VISIBILITY | DIRTY_HOTSPOT))))) {
+            status_t status;
+            if (!haveTransaction) {
+                status = mSurfaceComposerClient->openTransaction();
+                if (status) {
+                    LOGE("Error %d opening transation to update sprite surface.", status);
+                    break;
+                }
+                haveTransaction = true;
+            }
+
+            if (wantSurfaceVisibleAndDrawn
+                    && (becomingVisible || (update.state.dirty & DIRTY_ALPHA))) {
+                status = update.state.surfaceControl->setAlpha(update.state.alpha);
+                if (status) {
+                    LOGE("Error %d setting sprite surface alpha.", status);
+                }
+            }
+
+            if (wantSurfaceVisibleAndDrawn
+                    && (becomingVisible || (update.state.dirty & (DIRTY_POSITION
+                            | DIRTY_HOTSPOT)))) {
+                status = update.state.surfaceControl->setPosition(
+                        update.state.positionX - update.state.hotSpotX,
+                        update.state.positionY - update.state.hotSpotY);
+                if (status) {
+                    LOGE("Error %d setting sprite surface position.", status);
+                }
+            }
+
+            if (wantSurfaceVisibleAndDrawn
+                    && (becomingVisible
+                            || (update.state.dirty & DIRTY_TRANSFORMATION_MATRIX))) {
+                status = update.state.surfaceControl->setMatrix(
+                        update.state.transformationMatrix.dsdx,
+                        update.state.transformationMatrix.dtdx,
+                        update.state.transformationMatrix.dsdy,
+                        update.state.transformationMatrix.dtdy);
+                if (status) {
+                    LOGE("Error %d setting sprite surface transformation matrix.", status);
+                }
+            }
+
+            int32_t surfaceLayer = mOverlayLayer + update.state.layer;
+            if (wantSurfaceVisibleAndDrawn
+                    && (becomingVisible || (update.state.dirty & DIRTY_LAYER))) {
+                status = update.state.surfaceControl->setLayer(surfaceLayer);
+                if (status) {
+                    LOGE("Error %d setting sprite surface layer.", status);
+                }
+            }
+
+            if (becomingVisible) {
+                status = update.state.surfaceControl->show(surfaceLayer);
+                if (status) {
+                    LOGE("Error %d showing sprite surface.", status);
+                } else {
+                    update.state.surfaceVisible = true;
+                    update.surfaceChanged = surfaceChanged = true;
+                }
+            } else if (becomingHidden) {
+                status = update.state.surfaceControl->hide();
+                if (status) {
+                    LOGE("Error %d hiding sprite surface.", status);
+                } else {
+                    update.state.surfaceVisible = false;
+                    update.surfaceChanged = surfaceChanged = true;
+                }
+            }
+        }
+    }
+
+    if (haveTransaction) {
+        status_t status = mSurfaceComposerClient->closeTransaction();
+        if (status) {
+            LOGE("Error %d closing transaction to update sprite surface.", status);
+        }
+    }
+
+    // If any surfaces were changed, write back the new surface properties to the sprites.
+    if (surfaceChanged) { // acquire lock
+        AutoMutex _l(mLock);
+
+        for (size_t i = 0; i < numSprites; i++) {
+            const SpriteUpdate& update = updates.itemAt(i);
+
+            if (update.surfaceChanged) {
+                update.sprite->setSurfaceLocked(update.state.surfaceControl,
+                        update.state.surfaceWidth, update.state.surfaceHeight,
+                        update.state.surfaceDrawn, update.state.surfaceVisible);
+            }
+        }
+    } // release lock
+
+    // Clear the sprite update vector outside the lock.  It is very important that
+    // we do not clear sprite references inside the lock since we could be releasing
+    // the last remaining reference to the sprite here which would result in the
+    // sprite being deleted and the lock being reacquired by the sprite destructor
+    // while already held.
+    updates.clear();
+}
+
+void SpriteController::doDisposeSurfaces() {
+    // Collect disposed surfaces.
+    Vector<sp<SurfaceControl> > disposedSurfaces;
+    { // acquire lock
+        disposedSurfaces = mDisposedSurfaces;
+        mDisposedSurfaces.clear();
+    } // release lock
+
+    // Release the last reference to each surface outside of the lock.
+    // We don't want the surfaces to be deleted while we are holding our lock.
+    disposedSurfaces.clear();
+}
+
+void SpriteController::ensureSurfaceComposerClient() {
+    if (mSurfaceComposerClient == NULL) {
+        mSurfaceComposerClient = new SurfaceComposerClient();
+    }
+}
+
+sp<SurfaceControl> SpriteController::obtainSurface(int32_t width, int32_t height) {
+    ensureSurfaceComposerClient();
+
+    sp<SurfaceControl> surfaceControl = mSurfaceComposerClient->createSurface(
+            getpid(), String8("Sprite"), 0, width, height, PIXEL_FORMAT_RGBA_8888);
+    if (surfaceControl == NULL) {
+        LOGE("Error creating sprite surface.");
+        return NULL;
+    }
+    return surfaceControl;
+}
+
+
+// --- SpriteController::SpriteImpl ---
+
+SpriteController::SpriteImpl::SpriteImpl(const sp<SpriteController> controller) :
+        mController(controller), mTransactionNestingCount(0) {
+}
+
+SpriteController::SpriteImpl::~SpriteImpl() {
+    AutoMutex _m(mController->mLock);
+
+    // Let the controller take care of deleting the last reference to sprite
+    // surfaces so that we do not block the caller on an IPC here.
+    if (mState.surfaceControl != NULL) {
+        mController->disposeSurfaceLocked(mState.surfaceControl);
+        mState.surfaceControl.clear();
+    }
+}
+
+void SpriteController::SpriteImpl::setBitmap(const SkBitmap* bitmap,
+        float hotSpotX, float hotSpotY) {
+    AutoMutex _l(mController->mLock);
+
+    if (bitmap) {
+        bitmap->copyTo(&mState.bitmap, SkBitmap::kARGB_8888_Config);
+    } else {
+        mState.bitmap.reset();
+    }
+
+    uint32_t dirty = DIRTY_BITMAP;
+    if (mState.hotSpotX != hotSpotX || mState.hotSpotY != hotSpotY) {
+        mState.hotSpotX = hotSpotX;
+        mState.hotSpotY = hotSpotY;
+        dirty |= DIRTY_HOTSPOT;
+    }
+
+    invalidateLocked(dirty);
+}
+
+void SpriteController::SpriteImpl::setVisible(bool visible) {
+    AutoMutex _l(mController->mLock);
+
+    if (mState.visible != visible) {
+        mState.visible = visible;
+        invalidateLocked(DIRTY_VISIBILITY);
+    }
+}
+
+void SpriteController::SpriteImpl::setPosition(float x, float y) {
+    AutoMutex _l(mController->mLock);
+
+    if (mState.positionX != x || mState.positionY != y) {
+        mState.positionX = x;
+        mState.positionY = y;
+        invalidateLocked(DIRTY_POSITION);
+    }
+}
+
+void SpriteController::SpriteImpl::setLayer(int32_t layer) {
+    AutoMutex _l(mController->mLock);
+
+    if (mState.layer != layer) {
+        mState.layer = layer;
+        invalidateLocked(DIRTY_LAYER);
+    }
+}
+
+void SpriteController::SpriteImpl::setAlpha(float alpha) {
+    AutoMutex _l(mController->mLock);
+
+    if (mState.alpha != alpha) {
+        mState.alpha = alpha;
+        invalidateLocked(DIRTY_ALPHA);
+    }
+}
+
+void SpriteController::SpriteImpl::setTransformationMatrix(
+        const SpriteTransformationMatrix& matrix) {
+    AutoMutex _l(mController->mLock);
+
+    if (mState.transformationMatrix != matrix) {
+        mState.transformationMatrix = matrix;
+        invalidateLocked(DIRTY_TRANSFORMATION_MATRIX);
+    }
+}
+
+void SpriteController::SpriteImpl::openTransaction() {
+    AutoMutex _l(mController->mLock);
+
+    mTransactionNestingCount += 1;
+}
+
+void SpriteController::SpriteImpl::closeTransaction() {
+    AutoMutex _l(mController->mLock);
+
+    LOG_ALWAYS_FATAL_IF(mTransactionNestingCount == 0,
+            "Sprite closeTransaction() called but there is no open sprite transaction");
+
+    mTransactionNestingCount -= 1;
+    if (mTransactionNestingCount == 0 && mState.dirty) {
+        mController->invalidateSpriteLocked(this);
+    }
+}
+
+void SpriteController::SpriteImpl::invalidateLocked(uint32_t dirty) {
+    if (mTransactionNestingCount > 0) {
+        bool wasDirty = mState.dirty;
+        mState.dirty |= dirty;
+        if (!wasDirty) {
+            mController->invalidateSpriteLocked(this);
+        }
+    }
+}
+
+} // namespace android
diff --git a/services/input/SpriteController.h b/services/input/SpriteController.h
new file mode 100644
index 0000000..27afb5e
--- /dev/null
+++ b/services/input/SpriteController.h
@@ -0,0 +1,251 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_SPRITES_H
+#define _UI_SPRITES_H
+
+#include <utils/RefBase.h>
+#include <utils/Looper.h>
+
+#include <surfaceflinger/Surface.h>
+#include <surfaceflinger/SurfaceComposerClient.h>
+#include <surfaceflinger/ISurfaceComposer.h>
+
+#include <SkBitmap.h>
+
+namespace android {
+
+/*
+ * Transformation matrix for a sprite.
+ */
+struct SpriteTransformationMatrix {
+    inline SpriteTransformationMatrix() : dsdx(1.0f), dtdx(0.0f), dsdy(0.0f), dtdy(1.0f) { }
+
+    float dsdx;
+    float dtdx;
+    float dsdy;
+    float dtdy;
+
+    inline bool operator== (const SpriteTransformationMatrix& other) {
+        return dsdx == other.dsdx
+                && dtdx == other.dtdx
+                && dsdy == other.dsdy
+                && dtdy == other.dtdy;
+    }
+
+    inline bool operator!= (const SpriteTransformationMatrix& other) {
+        return !(*this == other);
+    }
+};
+
+/*
+ * A sprite is a simple graphical object that is displayed on-screen above other layers.
+ * The basic sprite class is an interface.
+ * The implementation is provided by the sprite controller.
+ */
+class Sprite : public RefBase {
+protected:
+    Sprite() { }
+    virtual ~Sprite() { }
+
+public:
+    /* Sets the bitmap that is drawn by the sprite.
+     * The sprite retains a copy of the bitmap for subsequent rendering. */
+    virtual void setBitmap(const SkBitmap* bitmap, float hotSpotX, float hotSpotY) = 0;
+
+    /* Sets whether the sprite is visible. */
+    virtual void setVisible(bool visible) = 0;
+
+    /* Sets the sprite position on screen, relative to the sprite's hot spot. */
+    virtual void setPosition(float x, float y) = 0;
+
+    /* Sets the layer of the sprite, relative to the system sprite overlay layer.
+     * Layer 0 is the overlay layer, > 0 appear above this layer. */
+    virtual void setLayer(int32_t layer) = 0;
+
+    /* Sets the sprite alpha blend ratio between 0.0 and 1.0. */
+    virtual void setAlpha(float alpha) = 0;
+
+    /* Sets the sprite transformation matrix. */
+    virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix) = 0;
+
+    /* Opens or closes a transaction to perform a batch of sprite updates as part of
+     * a single operation such as setPosition and setAlpha.  It is not necessary to
+     * open a transaction when updating a single property.
+     * Calls to openTransaction() nest and must be matched by an equal number
+     * of calls to closeTransaction(). */
+    virtual void openTransaction() = 0;
+    virtual void closeTransaction() = 0;
+};
+
+/*
+ * Displays sprites on the screen.
+ *
+ * This interface is used by PointerController and SpotController to draw pointers or
+ * spot representations of fingers.  It is not intended for general purpose use
+ * by other components.
+ *
+ * All sprite position updates and rendering is performed asynchronously.
+ *
+ * Clients are responsible for animating sprites by periodically updating their properties.
+ */
+class SpriteController : public MessageHandler {
+protected:
+    virtual ~SpriteController();
+
+public:
+    SpriteController(const sp<Looper>& looper, int32_t overlayLayer);
+
+    /* Creates a new sprite, initially invisible. */
+    sp<Sprite> createSprite();
+
+private:
+    enum {
+        MSG_UPDATE_SPRITES,
+        MSG_DISPOSE_SURFACES,
+    };
+
+    enum {
+        DIRTY_BITMAP = 1 << 0,
+        DIRTY_ALPHA = 1 << 1,
+        DIRTY_POSITION = 1 << 2,
+        DIRTY_TRANSFORMATION_MATRIX = 1 << 3,
+        DIRTY_LAYER = 1 << 4,
+        DIRTY_VISIBILITY = 1 << 5,
+        DIRTY_HOTSPOT = 1 << 6,
+    };
+
+    /* Describes the state of a sprite.
+     * This structure is designed so that it can be copied during updates so that
+     * surfaces can be resized and redrawn without blocking the client by holding a lock
+     * on the sprites for a long time.
+     * Note that the SkBitmap holds a reference to a shared (and immutable) pixel ref. */
+    struct SpriteState {
+        inline SpriteState() :
+                dirty(0), hotSpotX(0), hotSpotY(0), visible(false),
+                positionX(0), positionY(0), layer(0), alpha(1.0f),
+                surfaceWidth(0), surfaceHeight(0), surfaceDrawn(false), surfaceVisible(false) {
+        }
+
+        uint32_t dirty;
+
+        SkBitmap bitmap;
+        float hotSpotX;
+        float hotSpotY;
+        bool visible;
+        float positionX;
+        float positionY;
+        int32_t layer;
+        float alpha;
+        SpriteTransformationMatrix transformationMatrix;
+
+        sp<SurfaceControl> surfaceControl;
+        int32_t surfaceWidth;
+        int32_t surfaceHeight;
+        bool surfaceDrawn;
+        bool surfaceVisible;
+
+        inline bool wantSurfaceVisible() const {
+            return visible && alpha > 0.0f && !bitmap.isNull() && !bitmap.empty();
+        }
+    };
+
+    /* Client interface for a sprite.
+     * Requests acquire a lock on the controller, update local state and request the
+     * controller to invalidate the sprite.
+     * The real heavy lifting of creating, resizing and redrawing surfaces happens
+     * asynchronously with no locks held except in short critical section to copy
+     * the sprite state before the work and update the sprite surface control afterwards.
+     */
+    class SpriteImpl : public Sprite {
+    protected:
+        virtual ~SpriteImpl();
+
+    public:
+        SpriteImpl(const sp<SpriteController> controller);
+
+        virtual void setBitmap(const SkBitmap* bitmap, float hotSpotX, float hotSpotY);
+        virtual void setVisible(bool visible);
+        virtual void setPosition(float x, float y);
+        virtual void setLayer(int32_t layer);
+        virtual void setAlpha(float alpha);
+        virtual void setTransformationMatrix(const SpriteTransformationMatrix& matrix);
+        virtual void openTransaction();
+        virtual void closeTransaction();
+
+        inline const SpriteState& getStateLocked() const {
+            return mState;
+        }
+
+        inline void resetDirtyLocked() {
+            mState.dirty = 0;
+        }
+
+        inline void setSurfaceLocked(const sp<SurfaceControl>& surfaceControl,
+                int32_t width, int32_t height, bool drawn, bool visible) {
+            mState.surfaceControl = surfaceControl;
+            mState.surfaceWidth = width;
+            mState.surfaceHeight = height;
+            mState.surfaceDrawn = drawn;
+            mState.surfaceVisible = visible;
+        }
+
+    private:
+        sp<SpriteController> mController;
+
+        SpriteState mState; // guarded by mController->mLock
+        uint32_t mTransactionNestingCount; // guarded by mController->mLock
+
+        void invalidateLocked(uint32_t dirty);
+    };
+
+    /* Stores temporary information collected during the sprite update cycle. */
+    struct SpriteUpdate {
+        inline SpriteUpdate() : surfaceChanged(false) { }
+        inline SpriteUpdate(const sp<SpriteImpl> sprite, const SpriteState& state) :
+                sprite(sprite), state(state), surfaceChanged(false) {
+        }
+
+        sp<SpriteImpl> sprite;
+        SpriteState state;
+        bool surfaceChanged;
+    };
+
+    mutable Mutex mLock;
+
+    sp<Looper> mLooper;
+    const int32_t mOverlayLayer;
+    sp<WeakMessageHandler> mHandler;
+
+    sp<SurfaceComposerClient> mSurfaceComposerClient;
+
+    Vector<sp<SpriteImpl> > mInvalidatedSprites; // guarded by mLock
+    Vector<sp<SurfaceControl> > mDisposedSurfaces; // guarded by mLock
+
+    void invalidateSpriteLocked(const sp<SpriteImpl>& sprite);
+    void disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl);
+
+    void handleMessage(const Message& message);
+    void doUpdateSprites();
+    void doDisposeSurfaces();
+
+    void ensureSurfaceComposerClient();
+    sp<SurfaceControl> obtainSurface(int32_t width, int32_t height);
+};
+
+} // namespace android
+
+#endif // _UI_SPRITES_H
diff --git a/services/input/tests/InputReader_test.cpp b/services/input/tests/InputReader_test.cpp
index 4c5f239..ba8ca9c 100644
--- a/services/input/tests/InputReader_test.cpp
+++ b/services/input/tests/InputReader_test.cpp
@@ -192,6 +192,10 @@
     virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId) {
         return mPointerControllers.valueFor(deviceId);
     }
+
+    virtual sp<SpotControllerInterface> obtainSpotController(int32_t device) {
+        return NULL;
+    }
 };
 
 
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index f44b889..9990b7b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -13364,4 +13364,11 @@
             }
         }
     }
+
+    // Multi-user methods
+
+    public boolean switchUser(int userid) {
+        // TODO
+        return true;
+    }
 }
diff --git a/services/java/com/android/server/pm/UserDetails.java b/services/java/com/android/server/pm/UserDetails.java
new file mode 100644
index 0000000..2aeed7c
--- /dev/null
+++ b/services/java/com/android/server/pm/UserDetails.java
@@ -0,0 +1,305 @@
+/*
+ * 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 com.android.server.pm;
+
+import com.android.internal.util.FastXmlSerializer;
+
+import android.content.pm.UserInfo;
+import android.os.Environment;
+import android.os.FileUtils;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.Xml;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+public class UserDetails {
+    private static final String TAG_NAME = "name";
+
+    private static final String ATTR_FLAGS = "flags";
+
+    private static final String ATTR_ID = "id";
+
+    private static final String TAG_USERS = "users";
+
+    private static final String TAG_USER = "user";
+
+    private static final String TAG = "UserDetails";
+
+    private static final String USER_INFO_DIR = "system/users";
+    private static final String USER_LIST_FILENAME = "userlist.xml";
+
+    private SparseArray<UserInfo> mUsers;
+
+    private final File mUsersDir;
+    private final File mUserListFile;
+
+    /**
+     * Available for testing purposes.
+     */
+    UserDetails(File dataDir) {
+        mUsersDir = new File(dataDir, USER_INFO_DIR);
+        mUsersDir.mkdirs();
+        FileUtils.setPermissions(mUsersDir.toString(),
+                FileUtils.S_IRWXU|FileUtils.S_IRWXG
+                |FileUtils.S_IROTH|FileUtils.S_IXOTH,
+                -1, -1);
+        mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
+        readUserList();
+    }
+
+    public UserDetails() {
+        this(Environment.getDataDirectory());
+    }
+
+    public List<UserInfo> getUsers() {
+        ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
+        for (int i = 0; i < mUsers.size(); i++) {
+            users.add(mUsers.valueAt(i));
+        }
+        return users;
+    }
+
+    private void readUserList() {
+        mUsers = new SparseArray<UserInfo>();
+        if (!mUserListFile.exists()) {
+            fallbackToSingleUser();
+            return;
+        }
+        FileInputStream fis = null;
+        try {
+            fis = new FileInputStream(mUserListFile);
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(fis, null);
+            int type;
+            while ((type = parser.next()) != XmlPullParser.START_TAG
+                    && type != XmlPullParser.END_DOCUMENT) {
+                ;
+            }
+
+            if (type != XmlPullParser.START_TAG) {
+                Slog.e(TAG, "Unable to read user list");
+                fallbackToSingleUser();
+                return;
+            }
+
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+                if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
+                    String id = parser.getAttributeValue(null, ATTR_ID);
+                    UserInfo user = readUser(Integer.parseInt(id));
+                    if (user != null) {
+                        mUsers.put(user.id, user);
+                    }
+                }
+            }
+        } catch (IOException ioe) {
+            fallbackToSingleUser();
+        } catch (XmlPullParserException pe) {
+            fallbackToSingleUser();
+        }
+    }
+
+    private void fallbackToSingleUser() {
+        // Create the primary user
+        UserInfo primary = new UserInfo(0, "Primary",
+                UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY);
+        mUsers.put(0, primary);
+
+        writeUserList();
+        writeUser(primary);
+    }
+
+    /*
+     * Writes the user file in this format:
+     *
+     * <user flags="20039023" id="0">
+     *   <name>Primary</name>
+     * </user>
+     */
+    private void writeUser(UserInfo userInfo) {
+        try {
+            final File mUserFile = new File(mUsersDir, userInfo.id + ".xml");
+            final FileOutputStream fos = new FileOutputStream(mUserFile);
+            final BufferedOutputStream bos = new BufferedOutputStream(fos);
+
+            // XmlSerializer serializer = XmlUtils.serializerInstance();
+            final XmlSerializer serializer = new FastXmlSerializer();
+            serializer.setOutput(bos, "utf-8");
+            serializer.startDocument(null, true);
+            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+
+            serializer.startTag(null, TAG_USER);
+            serializer.attribute(null, ATTR_ID, Integer.toString(userInfo.id));
+            serializer.attribute(null, ATTR_FLAGS, Integer.toString(userInfo.flags));
+
+            serializer.startTag(null, TAG_NAME);
+            serializer.text(userInfo.name);
+            serializer.endTag(null, TAG_NAME);
+
+            serializer.endTag(null, TAG_USER);
+
+            serializer.endDocument();
+        } catch (IOException ioe) {
+            Slog.e(TAG, "Error writing user info " + userInfo.id + "\n" + ioe);
+        }
+    }
+
+    /*
+     * Writes the user list file in this format:
+     *
+     * <users>
+     *   <user id="0"></user>
+     *   <user id="2"></user>
+     * </users>
+     */
+    private void writeUserList() {
+        try {
+            final FileOutputStream fos = new FileOutputStream(mUserListFile);
+            final BufferedOutputStream bos = new BufferedOutputStream(fos);
+
+            // XmlSerializer serializer = XmlUtils.serializerInstance();
+            final XmlSerializer serializer = new FastXmlSerializer();
+            serializer.setOutput(bos, "utf-8");
+            serializer.startDocument(null, true);
+            serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+
+            serializer.startTag(null, TAG_USERS);
+
+            for (int i = 0; i < mUsers.size(); i++) {
+                UserInfo user = mUsers.valueAt(i);
+                serializer.startTag(null, TAG_USER);
+                serializer.attribute(null, ATTR_ID, Integer.toString(user.id));
+                serializer.endTag(null, TAG_USER);
+                Slog.e(TAG, "Wrote user " + user.id + " to userlist.xml");
+            }
+
+            serializer.endTag(null, TAG_USERS);
+
+            serializer.endDocument();
+        } catch (IOException ioe) {
+            Slog.e(TAG, "Error writing user list");
+        }
+    }
+
+    private UserInfo readUser(int id) {
+        int flags = 0;
+        String name = null;
+
+        FileInputStream fis = null;
+        try {
+            File userFile = new File(mUsersDir, Integer.toString(id) + ".xml");
+            fis = new FileInputStream(userFile);
+            XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(fis, null);
+            int type;
+            while ((type = parser.next()) != XmlPullParser.START_TAG
+                    && type != XmlPullParser.END_DOCUMENT) {
+                ;
+            }
+
+            if (type != XmlPullParser.START_TAG) {
+                Slog.e(TAG, "Unable to read user " + id);
+                return null;
+            }
+
+            if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_USER)) {
+                String storedId = parser.getAttributeValue(null, ATTR_ID);
+                if (Integer.parseInt(storedId) != id) {
+                    Slog.e(TAG, "User id does not match the file name");
+                    return null;
+                }
+                String flagString = parser.getAttributeValue(null, ATTR_FLAGS);
+                flags = Integer.parseInt(flagString);
+
+                while ((type = parser.next()) != XmlPullParser.START_TAG
+                        && type != XmlPullParser.END_DOCUMENT) {
+                }
+                if (type == XmlPullParser.START_TAG && parser.getName().equals(TAG_NAME)) {
+                    type = parser.next();
+                    if (type == XmlPullParser.TEXT) {
+                        name = parser.getText();
+                    }
+                }
+            }
+            fis.close();
+
+            UserInfo userInfo = new UserInfo(id, name, flags);
+            return userInfo;
+
+        } catch (IOException ioe) {
+        } catch (XmlPullParserException pe) {
+        }
+        return null;
+    }
+
+    public UserInfo createUser(String name, int flags) {
+        int id = getNextAvailableId();
+        UserInfo userInfo = new UserInfo(id, name, flags);
+        if (!createPackageFolders(id)) {
+            return null;
+        }
+        mUsers.put(id, userInfo);
+        writeUserList();
+        writeUser(userInfo);
+        return userInfo;
+    }
+
+    public void removeUser(int id) {
+        // Remove from the list
+        UserInfo userInfo = mUsers.get(id);
+        if (userInfo != null) {
+            // Remove this user from the list
+            mUsers.remove(id);
+            // Remove user file
+            File userFile = new File(mUsersDir, id + ".xml");
+            userFile.delete();
+            writeUserList();
+            removePackageFolders(id);
+        }
+    }
+
+    private int getNextAvailableId() {
+        int i = 0;
+        while (i < Integer.MAX_VALUE) {
+            if (mUsers.indexOfKey(i) < 0) {
+                break;
+            }
+            i++;
+        }
+        return i;
+    }
+
+    private boolean createPackageFolders(int id) {
+        // TODO: Create data directories for all the packages for a new user, w/ specified user id.
+        return true;
+    }
+
+    private boolean removePackageFolders(int id) {
+        // TODO: Remove all the data directories for the specified user.
+        return true;
+    }
+}
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index ab2c125..aaa305e 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -36,6 +36,8 @@
 
 #include <input/InputManager.h>
 #include <input/PointerController.h>
+#include <input/SpotController.h>
+#include <input/SpriteController.h>
 
 #include <android_os_MessageQueue.h>
 #include <android_view_KeyEvent.h>
@@ -163,6 +165,7 @@
     virtual nsecs_t getVirtualKeyQuietTime();
     virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames);
     virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
+    virtual sp<SpotControllerInterface> obtainSpotController(int32_t deviceId);
 
     /* --- InputDispatcherPolicyInterface implementation --- */
 
@@ -213,12 +216,16 @@
         // System UI visibility.
         int32_t systemUiVisibility;
 
+        // Sprite controller singleton, created on first use.
+        sp<SpriteController> spriteController;
+
         // Pointer controller singleton, created and destroyed as needed.
         wp<PointerController> pointerController;
     } mLocked;
 
     void updateInactivityFadeDelayLocked(const sp<PointerController>& controller);
     void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
+    void ensureSpriteControllerLocked();
 
     // Power manager interactions.
     bool isScreenOn();
@@ -419,18 +426,15 @@
 
     sp<PointerController> controller = mLocked.pointerController.promote();
     if (controller == NULL) {
-        JNIEnv* env = jniEnv();
-        jint layer = env->CallIntMethod(mCallbacksObj, gCallbacksClassInfo.getPointerLayer);
-        if (checkAndClearExceptionFromCallback(env, "getPointerLayer")) {
-            layer = -1;
-        }
+        ensureSpriteControllerLocked();
 
-        controller = new PointerController(mLooper, layer);
+        controller = new PointerController(mLooper, mLocked.spriteController);
         mLocked.pointerController = controller;
 
         controller->setDisplaySize(mLocked.displayWidth, mLocked.displayHeight);
         controller->setDisplayOrientation(mLocked.displayOrientation);
 
+        JNIEnv* env = jniEnv();
         jobject iconObj = env->CallObjectMethod(mCallbacksObj, gCallbacksClassInfo.getPointerIcon);
         if (!checkAndClearExceptionFromCallback(env, "getPointerIcon") && iconObj) {
             jfloat iconHotSpotX = env->GetFloatField(iconObj, gPointerIconClassInfo.hotSpotX);
@@ -451,6 +455,24 @@
     return controller;
 }
 
+sp<SpotControllerInterface> NativeInputManager::obtainSpotController(int32_t deviceId) {
+    AutoMutex _l(mLock);
+
+    ensureSpriteControllerLocked();
+    return new SpotController(mLooper, mLocked.spriteController);
+}
+
+void NativeInputManager::ensureSpriteControllerLocked() {
+    if (mLocked.spriteController == NULL) {
+        JNIEnv* env = jniEnv();
+        jint layer = env->CallIntMethod(mCallbacksObj, gCallbacksClassInfo.getPointerLayer);
+        if (checkAndClearExceptionFromCallback(env, "getPointerLayer")) {
+            layer = -1;
+        }
+        mLocked.spriteController = new SpriteController(mLooper, layer);
+    }
+}
+
 void NativeInputManager::notifySwitch(nsecs_t when, int32_t switchCode,
         int32_t switchValue, uint32_t policyFlags) {
 #if DEBUG_INPUT_DISPATCHER_POLICY
diff --git a/services/jni/com_android_server_UsbService.cpp b/services/jni/com_android_server_UsbService.cpp
index 00ee7e3..9cd04f6 100644
--- a/services/jni/com_android_server_UsbService.cpp
+++ b/services/jni/com_android_server_UsbService.cpp
@@ -37,13 +37,6 @@
 namespace android
 {
 
-static struct file_descriptor_offsets_t
-{
-    jclass mClass;
-    jmethodID mConstructor;
-    jfieldID mDescriptor;
-} gFileDescriptorOffsets;
-
 static struct parcel_file_descriptor_offsets_t
 {
     jclass mClass;
@@ -167,11 +160,8 @@
     int newFD = dup(fd);
     usb_device_close(device);
 
-    jobject fileDescriptor = env->NewObject(gFileDescriptorOffsets.mClass,
-        gFileDescriptorOffsets.mConstructor);
-    if (fileDescriptor != NULL) {
-        env->SetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor, newFD);
-    } else {
+    jobject fileDescriptor = jniCreateFileDescriptor(env, newFD);
+    if (fileDescriptor == NULL) {
         return NULL;
     }
     return env->NewObject(gParcelFileDescriptorOffsets.mClass,
@@ -221,11 +211,8 @@
         LOGE("could not open %s", DRIVER_NAME);
         return NULL;
     }
-    jobject fileDescriptor = env->NewObject(gFileDescriptorOffsets.mClass,
-        gFileDescriptorOffsets.mConstructor);
-    if (fileDescriptor != NULL) {
-        env->SetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor, fd);
-    } else {
+    jobject fileDescriptor = jniCreateFileDescriptor(env, fd);
+    if (fileDescriptor == NULL) {
         return NULL;
     }
     return env->NewObject(gParcelFileDescriptorOffsets.mClass,
@@ -260,14 +247,6 @@
         return -1;
     }
 
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
-    gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
-    gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL,
-                 "Unable to find descriptor field in java.io.FileDescriptor");
-
     clazz = env->FindClass("android/os/ParcelFileDescriptor");
     LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
     gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index f115f42..2fcce78 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.frameworks.servicestests">
+        package="com.android.frameworks.servicestests">
 
     <uses-permission android:name="android.permission.READ_LOGS" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserDetailsTest.java b/services/tests/servicestests/src/com/android/server/pm/UserDetailsTest.java
new file mode 100644
index 0000000..7b77aac
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/UserDetailsTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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 com.android.server.pm;
+
+import com.android.server.pm.UserDetails;
+
+import android.content.pm.UserInfo;
+import android.os.Debug;
+import android.os.Environment;
+import android.test.AndroidTestCase;
+
+import java.util.List;
+
+/** Test {@link UserDetails} functionality. */
+public class UserDetailsTest extends AndroidTestCase {
+
+    UserDetails mDetails = null;
+
+    @Override
+    public void setUp() throws Exception {
+        mDetails = new UserDetails(Environment.getExternalStorageDirectory());
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        List<UserInfo> users = mDetails.getUsers();
+        // Remove all except the primary user
+        for (UserInfo user : users) {
+            if (!user.isPrimary()) {
+                mDetails.removeUser(user.id);
+            }
+        }
+    }
+
+    public void testHasPrimary() throws Exception {
+        assertTrue(findUser(0));
+    }
+
+    public void testAddUser() throws Exception {
+        final UserDetails details = mDetails;
+
+        UserInfo userInfo = details.createUser("Guest 1", UserInfo.FLAG_GUEST);
+        assertTrue(userInfo != null);
+
+        List<UserInfo> list = details.getUsers();
+        boolean found = false;
+        for (UserInfo user : list) {
+            if (user.id == userInfo.id && user.name.equals("Guest 1")
+                    && user.isGuest()
+                    && !user.isAdmin()
+                    && !user.isPrimary()) {
+                found = true;
+            }
+        }
+        assertTrue(found);
+    }
+
+    public void testAdd2Users() throws Exception {
+        final UserDetails details = mDetails;
+
+        UserInfo user1 = details.createUser("Guest 1", UserInfo.FLAG_GUEST);
+        UserInfo user2 = details.createUser("User 2", UserInfo.FLAG_ADMIN);
+
+        assertTrue(user1 != null);
+        assertTrue(user2 != null);
+
+        assertTrue(findUser(0));
+        assertTrue(findUser(user1.id));
+        assertTrue(findUser(user2.id));
+    }
+
+    public void testRemoveUser() throws Exception {
+        final UserDetails details = mDetails;
+
+        UserInfo userInfo = details.createUser("Guest 1", UserInfo.FLAG_GUEST);
+
+        details.removeUser(userInfo.id);
+
+        assertFalse(findUser(userInfo.id));
+    }
+
+    private boolean findUser(int id) {
+        List<UserInfo> list = mDetails.getUsers();
+
+        for (UserInfo user : list) {
+            if (user.id == id) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 0d20496..d84f1e5 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -23,32 +23,30 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.FeatureInfo;
-import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.IPackageDataObserver;
+import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.IPackageInstallObserver;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.os.RemoteException;
 
 import java.util.List;
 
 /**
  * A mock {@link android.content.pm.PackageManager} class.  All methods are non-functional and throw
- * {@link java.lang.UnsupportedOperationException}. Override it to provide the operations that you 
+ * {@link java.lang.UnsupportedOperationException}. Override it to provide the operations that you
  * need.
  */
 public class MockPackageManager extends PackageManager {
@@ -63,12 +61,12 @@
     public String[] currentToCanonicalPackageNames(String[] names) {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public String[] canonicalToCurrentPackageNames(String[] names) {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public Intent getLaunchIntentForPackage(String packageName) {
         throw new UnsupportedOperationException();
@@ -101,7 +99,7 @@
     public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public ApplicationInfo getApplicationInfo(String packageName, int flags)
     throws NameNotFoundException {
@@ -176,7 +174,7 @@
     public String getNameForUid(int uid) {
         throw new UnsupportedOperationException();
     }
-    
+
     /**
      * @hide - to match hiding in superclass
      */
@@ -273,7 +271,7 @@
     public Drawable getApplicationIcon(String packageName) throws NameNotFoundException {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public Drawable getActivityLogo(ComponentName activityName) throws NameNotFoundException {
         throw new UnsupportedOperationException();
@@ -354,7 +352,7 @@
     public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public String getInstallerPackageName(String packageName) {
         throw new UnsupportedOperationException();
@@ -368,7 +366,7 @@
             String packageName, IPackageDataObserver observer) {
         throw new UnsupportedOperationException();
     }
-    
+
     /**
      * @hide - to match hiding in superclass
      */
@@ -377,7 +375,7 @@
             String packageName, IPackageDataObserver observer) {
         throw new UnsupportedOperationException();
     }
-    
+
     /**
      * @hide - to match hiding in superclass
      */
@@ -435,7 +433,7 @@
     public void setApplicationEnabledSetting(String packageName, int newState, int flags) {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public int getApplicationEnabledSetting(String packageName) {
         throw new UnsupportedOperationException();
@@ -446,7 +444,7 @@
             int match, ComponentName[] set, ComponentName activity) {
         throw new UnsupportedOperationException();
     }
-    
+
     /**
      * @hide - to match hiding in superclass
      */
@@ -475,24 +473,64 @@
             List<ComponentName> outActivities, String packageName) {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public String[] getSystemSharedLibraryNames() {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public FeatureInfo[] getSystemAvailableFeatures() {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public boolean hasSystemFeature(String name) {
         throw new UnsupportedOperationException();
     }
-    
+
     @Override
     public boolean isSafeMode() {
         throw new UnsupportedOperationException();
     }
+
+    /**
+     * @hide
+     */
+    @Override
+    public UserInfo createUser(String name, int flags) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public List<UserInfo> getUsers() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean removeUser(int id) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void updateUserName(int id, String name) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void updateUserFlags(int id, int flags) {
+        throw new UnsupportedOperationException();
+    }
 }