improve glgen tool to support EGL1.4

- added EGL1.4 bindings generation
- fixed bugs in GLES bindings

Bug: 6709865
Change-Id: I04ac63f652e1968a51eb833f47e00336ea449980
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 31f4190..3359a22 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -12,6 +12,7 @@
 mkdir -p out/com/google/android/gles_jni
 mkdir -p out/android/app
 mkdir -p out/android/graphics
+mkdir -p out/android/view
 mkdir -p out/android/opengl
 mkdir -p out/android/content
 mkdir -p out/android/content/pm
@@ -24,15 +25,33 @@
 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
+echo "package android.content.pm; public interface IPackageManager {ApplicationInfo getApplicationInfo(java.lang.String packageName, int flags, java.lang.String userId) throws android.os.RemoteException;}" > out/android/content/pm/IPackageManager.java
 echo "package android.os; public class Build {public static class VERSION_CODES { public static final int CUPCAKE = 3;};	}" > out/android/os/Build.java
+echo "package android.os; public class UserId {public static String myUserId() { return \"\"; } }" > out/android/os/UserId.java
 echo "package android.os; public class RemoteException extends Exception {}" > out/android/os/RemoteException.java
 echo "package android.util; public class Log {public static void w(String a, String b) {} public static void e(String a, String b) {}}" > out/android/util/Log.java
 
+echo "package android.opengl; public abstract class EGLObjectHandle { public int getHandle() { return 0; } }" > out/android/opengl/EGLObjectHandle.java
+echo "package android.opengl; public class EGLSurface extends EGLObjectHandle {  }" > out/android/opengl/EGLSurface.java
+echo "package android.opengl; public class EGLContext extends EGLObjectHandle {  }" > out/android/opengl/EGLContext.java
+echo "package android.opengl; public class EGLDisplay extends EGLObjectHandle {  }" > out/android/opengl/EGLDisplay.java
+echo "package android.opengl; public class EGLConfig extends EGLObjectHandle {  }" > out/android/opengl/EGLConfig.java
+
+
+echo "package android.graphics;" > out/android/graphics/SurfaceTexture.java
+echo "public interface SurfaceTexture {}" >> out/android/graphics/SurfaceTexture.java
+echo "package android.view;" > out/android/view/SurfaceView.java
+echo "public interface SurfaceView { SurfaceHolder getHolder(); }" >> out/android/view/SurfaceView.java
+echo "package android.view;" > out/android/view/Surface.java
+echo "public interface Surface {}" >> out/android/view/Surface.java
+echo "package android.view;" > out/android/view/SurfaceHolder.java
+echo "public interface SurfaceHolder { Surface getSurface(); }" >> out/android/view/SurfaceHolder.java
+
+
 GLFILE=out/javax/microedition/khronos/opengles/GL.java
 cp stubs/jsr239/GLHeader.java-if $GLFILE
 
-GLGEN_FILES="CFunc.java CType.java CodeEmitter.java GenerateGL.java GenerateGLES.java GLESCodeEmitter.java JFunc.java JniCodeEmitter.java JType.java Jsr239CodeEmitter.java ParameterChecker.java"
+GLGEN_FILES="CFunc.java CType.java CodeEmitter.java EGLCodeEmitter.java GenerateEGL.java GenerateGL.java GenerateGLES.java GLESCodeEmitter.java JFunc.java JniCodeEmitter.java JType.java Jsr239CodeEmitter.java ParameterChecker.java"
 
 pushd src > /dev/null
 javac ${GLGEN_FILES}
@@ -59,11 +78,19 @@
     exit $JAVA_RESULT
 fi
 
+echo "Generating static EGL 1.4 bindings"
+java -classpath src GenerateEGL
+JAVA_RESULT=$?
+if [ $JAVA_RESULT -ne 0 ]; then
+    echo "Could not run GenerateEGL."
+    exit $JAVA_RESULT
+fi
+
 rm src/*.class
 
 pushd out > /dev/null
 mkdir classes
-javac -d classes com/google/android/gles_jni/GLImpl.java javax/microedition/khronos/opengles/GL10.java javax/microedition/khronos/opengles/GL10Ext.java javax/microedition/khronos/opengles/GL11.java javax/microedition/khronos/opengles/GL11Ext.java javax/microedition/khronos/opengles/GL11ExtensionPack.java android/opengl/GLES10.java android/opengl/GLES10Ext.java android/opengl/GLES11.java android/opengl/GLES11Ext.java android/opengl/GLES20.java
+javac -d classes android/opengl/EGL14.java com/google/android/gles_jni/GLImpl.java javax/microedition/khronos/opengles/GL10.java javax/microedition/khronos/opengles/GL10Ext.java javax/microedition/khronos/opengles/GL11.java javax/microedition/khronos/opengles/GL11Ext.java javax/microedition/khronos/opengles/GL11ExtensionPack.java android/opengl/GLES10.java android/opengl/GLES10Ext.java android/opengl/GLES11.java android/opengl/GLES11Ext.java android/opengl/GLES20.java
 popd > /dev/null
 JAVA_RESULT=$?
 if [ $JAVA_RESULT -ne 0 ]; then
@@ -90,6 +117,7 @@
     if cmp -s $1/$3 $2/$3 ; then
         echo "#    " $3 unchanged
     else
+        echo "#    " $3 changed
         if [ $SAID_PLEASE == "0" ] ; then
             echo Please evaluate the following commands:
             echo
@@ -101,18 +129,18 @@
     fi
 }
 
-compareGenerated ../../../core/jni generated/C com_google_android_gles_jni_GLImpl.cpp
-compareGenerated ../../java/com/google/android/gles_jni generated/com/google/android/gles_jni GLImpl.java
+compareGenerated ../../../../base/core/jni generated/C com_google_android_gles_jni_GLImpl.cpp
+compareGenerated ../../../../base/opengl/java/com/google/android/gles_jni generated/com/google/android/gles_jni GLImpl.java
 
 for x in GL.java GL10.java GL10Ext.java GL11.java GL11Ext.java GL11ExtensionPack.java
 do
-    compareGenerated ../../java/javax/microedition/khronos/opengles generated/javax/microedition/khronos/opengles $x
+    compareGenerated ../../../../base/opengl/java/javax/microedition/khronos/opengles generated/javax/microedition/khronos/opengles $x
 done
 
-for x in GLES10 GLES10Ext GLES11 GLES11Ext GLES20
+for x in EGL14 GLES10 GLES10Ext GLES11 GLES11Ext GLES20
 do
-    compareGenerated ../../java/android/opengl generated/android/opengl ${x}.java
-    compareGenerated ../../../core/jni generated/C android_opengl_${x}.cpp
+    compareGenerated ../../../../base/opengl/java/android/opengl generated/android/opengl ${x}.java
+    compareGenerated ../../../../base/core/jni generated/C android_opengl_${x}.cpp
 done
 
 if [ $KEEP_GENERATED == "0" ] ; then
diff --git a/opengl/tools/glgen/specs/egl/EGL14.spec b/opengl/tools/glgen/specs/egl/EGL14.spec
new file mode 100644
index 0000000..828e114
--- /dev/null
+++ b/opengl/tools/glgen/specs/egl/EGL14.spec
@@ -0,0 +1,33 @@
+EGLint eglGetError ( void )
+EGLDisplay eglGetDisplay ( EGLNativeDisplayType display_id )
+EGLBoolean eglInitialize ( EGLDisplay dpy, EGLint *major, EGLint *minor )
+EGLBoolean eglTerminate ( EGLDisplay dpy )
+const char * eglQueryString ( EGLDisplay dpy, EGLint name )
+EGLBoolean eglGetConfigs ( EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config )
+EGLBoolean eglChooseConfig ( EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config )
+EGLBoolean eglGetConfigAttrib ( EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value )
+EGLSurface eglCreateWindowSurface ( EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list )
+EGLSurface eglCreatePbufferSurface ( EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list )
+EGLSurface eglCreatePixmapSurface ( EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list )
+EGLBoolean eglDestroySurface ( EGLDisplay dpy, EGLSurface surface )
+EGLBoolean eglQuerySurface ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value )
+EGLBoolean eglBindAPI ( EGLenum api )
+EGLenum eglQueryAPI ( void )
+EGLBoolean eglWaitClient ( void )
+EGLBoolean eglReleaseThread ( void )
+EGLSurface eglCreatePbufferFromClientBuffer ( EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list )
+EGLBoolean eglSurfaceAttrib ( EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value )
+EGLBoolean eglBindTexImage ( EGLDisplay dpy, EGLSurface surface, EGLint buffer )
+EGLBoolean eglReleaseTexImage ( EGLDisplay dpy, EGLSurface surface, EGLint buffer )
+EGLBoolean eglSwapInterval ( EGLDisplay dpy, EGLint interval )
+EGLContext eglCreateContext ( EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list )
+EGLBoolean eglDestroyContext ( EGLDisplay dpy, EGLContext ctx )
+EGLBoolean eglMakeCurrent ( EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx )
+EGLContext eglGetCurrentContext ( void )
+EGLSurface eglGetCurrentSurface ( EGLint readdraw )
+EGLDisplay eglGetCurrentDisplay ( void )
+EGLBoolean eglQueryContext ( EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value )
+EGLBoolean eglWaitGL ( void )
+EGLBoolean eglWaitNative ( EGLint engine )
+EGLBoolean eglSwapBuffers ( EGLDisplay dpy, EGLSurface surface )
+EGLBoolean eglCopyBuffers ( EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target )
diff --git a/opengl/tools/glgen/specs/egl/checks.spec b/opengl/tools/glgen/specs/egl/checks.spec
new file mode 100644
index 0000000..34fb1ee
--- /dev/null
+++ b/opengl/tools/glgen/specs/egl/checks.spec
@@ -0,0 +1,13 @@
+eglInitialize check major 1 check minor 1
+eglGetConfigs check configs config_size
+eglChooseConfig check configs config_size check num_config 1 sentinel attrib_list EGL_NONE
+eglGetConfigAttrib check value 1
+//STUB function: //eglCreateWindowSurface sentinel attrib_list EGL_NONE
+eglCreatePbufferSurface sentinel attrib_list EGL_NONE
+//unsupported: eglCreatePixmapSurface sentinel attrib_list EGL_NONE
+eglCreatePixmapSurface unsupported
+eglCopyBuffers unsupported
+eglQuerySurface check value 1
+eglCreatePbufferFromClientBuffer sentinel attrib_list EGL_NONE
+eglCreateContext sentinel attrib_list EGL_NONE
+eglQueryContext check value 1
diff --git a/opengl/tools/glgen/src/CFunc.java b/opengl/tools/glgen/src/CFunc.java
index 4847694..a192c00 100644
--- a/opengl/tools/glgen/src/CFunc.java
+++ b/opengl/tools/glgen/src/CFunc.java
@@ -28,6 +28,7 @@
 
     boolean hasPointerArg = false;
     boolean hasTypedPointerArg = false;
+    boolean hasEGLHandleArg = false;
 
     public CFunc(String original) {
         this.original = original;
@@ -63,6 +64,9 @@
         if (argType.isTypedPointer()) {
             hasTypedPointerArg = true;
         }
+        if (argType.isEGLHandle()) {
+            hasEGLHandleArg = true;
+        }
     }
 
     public int getNumArgs() {
@@ -95,6 +99,10 @@
         return hasTypedPointerArg;
     }
 
+    public boolean hasEGLHandleArg() {
+        return hasEGLHandleArg;
+    }
+
     @Override
     public String toString() {
         String s =  "Function " + fname + " returns " + ftype + ": ";
diff --git a/opengl/tools/glgen/src/CType.java b/opengl/tools/glgen/src/CType.java
index e0f0ca6..92950ea 100644
--- a/opengl/tools/glgen/src/CType.java
+++ b/opengl/tools/glgen/src/CType.java
@@ -53,6 +53,16 @@
     return isPointer;
     }
 
+    public boolean isEGLHandle() {
+        if(baseType.equals("EGLContext")
+           || baseType.equals("EGLConfig")
+           || baseType.equals("EGLSurface")
+           || baseType.equals("EGLDisplay")) {
+               return true;
+        }
+        return false;
+    }
+
     boolean isVoid() {
     String baseType = getBaseType();
     return baseType.equals("GLvoid") ||
diff --git a/opengl/tools/glgen/src/EGLCodeEmitter.java b/opengl/tools/glgen/src/EGLCodeEmitter.java
new file mode 100644
index 0000000..1691b65
--- /dev/null
+++ b/opengl/tools/glgen/src/EGLCodeEmitter.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2012 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.
+ */
+
+import java.io.PrintStream;
+
+/**
+ * Emits a Java interface and Java & C implementation for a C function.
+ *
+ * <p> The Java interface will have Buffer and array variants for functions that
+ * have a typed pointer argument.  The array variant will convert a single "<type> *data"
+ * argument to a pair of arguments "<type>[] data, int offset".
+ */
+public class EGLCodeEmitter extends JniCodeEmitter {
+
+    PrintStream mJavaImplStream;
+    PrintStream mCStream;
+
+    PrintStream mJavaInterfaceStream;
+
+    /**
+      */
+    public EGLCodeEmitter(String classPathName,
+                          ParameterChecker checker,
+                          PrintStream javaImplStream,
+                          PrintStream cStream) {
+        mClassPathName = classPathName;
+        mChecker = checker;
+
+        mJavaImplStream = javaImplStream;
+        mCStream = cStream;
+        mUseContextPointer = false;
+        mUseStaticMethods = true;
+        mUseSimpleMethodNames = true;
+        mUseHideCommentForAPI = true;
+    }
+
+    public void emitCode(CFunc cfunc, String original) {
+        emitCode(cfunc, original, null, mJavaImplStream,
+                mCStream);
+    }
+
+    public void emitNativeRegistration(String nativeRegistrationName) {
+        emitNativeRegistration(nativeRegistrationName, mCStream);
+    }
+}
diff --git a/opengl/tools/glgen/src/GenerateEGL.java b/opengl/tools/glgen/src/GenerateEGL.java
new file mode 100644
index 0000000..aaa748c
--- /dev/null
+++ b/opengl/tools/glgen/src/GenerateEGL.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2012 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.
+ */
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintStream;
+
+public class GenerateEGL {
+
+    private static void copy(String filename, PrintStream out) throws IOException {
+        BufferedReader br = new BufferedReader(new FileReader(filename));
+        String s;
+        while ((s = br.readLine()) != null) {
+            out.println(s);
+        }
+    }
+
+    private static void emit(EGLCodeEmitter emitter,
+                             BufferedReader specReader,
+                             PrintStream glStream,
+                             PrintStream cStream) throws Exception {
+        String s = null;
+        while ((s = specReader.readLine()) != null) {
+            if (s.trim().startsWith("//")) {
+                continue;
+            }
+
+            CFunc cfunc = CFunc.parseCFunc(s);
+
+            String fname = cfunc.getName();
+            String stubRoot = "stubs/egl/" + fname;
+            String javaPath = stubRoot + ".java";
+            File f = new File(javaPath);
+            if (f.exists()) {
+                System.out.println("Special-casing function " + fname);
+                copy(javaPath, glStream);
+                copy(stubRoot + ".cpp", cStream);
+
+                // Register native function names
+                // This should be improved to require fewer discrete files
+                String filename = stubRoot + ".nativeReg";
+                BufferedReader br =
+                    new BufferedReader(new FileReader(filename));
+                String nfunc;
+                while ((nfunc = br.readLine()) != null) {
+                    emitter.addNativeRegistration(nfunc);
+                }
+            } else {
+                emitter.emitCode(cfunc, s);
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        int aidx = 0;
+        while ((aidx < args.length) && (args[aidx].charAt(0) == '-')) {
+            switch (args[aidx].charAt(1)) {
+            default:
+                System.err.println("Unknown flag: " + args[aidx]);
+                System.exit(1);
+            }
+
+            aidx++;
+        }
+
+        BufferedReader checksReader =
+            new BufferedReader(new FileReader("specs/egl/checks.spec"));
+        ParameterChecker checker = new ParameterChecker(checksReader);
+
+
+        BufferedReader specReader =
+                new BufferedReader(new FileReader("specs/egl/EGL14.spec"));
+
+        String egljFilename = "android/opengl/EGL14.java";
+        String eglcFilename = "android_opengl_EGL14.cpp";
+        PrintStream egljStream =
+            new PrintStream(new FileOutputStream("out/" + egljFilename));
+        PrintStream eglcStream =
+            new PrintStream(new FileOutputStream("out/" + eglcFilename));
+        egljStream.println("/*");
+        eglcStream.println("/*");
+        copy("stubs/egl/EGL14Header.java-if", egljStream);
+        copy("stubs/egl/EGL14cHeader.cpp", eglcStream);
+        EGLCodeEmitter emitter = new EGLCodeEmitter(
+                "android/opengl/EGL14",
+                checker, egljStream, eglcStream);
+        emit(emitter, specReader, egljStream, eglcStream);
+        emitter.emitNativeRegistration("register_android_opengl_jni_EGL14");
+        egljStream.println("}");
+        egljStream.close();
+        eglcStream.close();
+    }
+}
diff --git a/opengl/tools/glgen/src/JType.java b/opengl/tools/glgen/src/JType.java
index deb2f01..3f7cb73 100644
--- a/opengl/tools/glgen/src/JType.java
+++ b/opengl/tools/glgen/src/JType.java
@@ -48,6 +48,22 @@
     typeMapping.put(new CType("char", true, true), new JType("String", false, false));
     typeMapping.put(new CType("int"), new JType("int"));
 
+    // EGL primitive types
+    typeMapping.put(new CType("EGLint"), new JType("int"));
+    typeMapping.put(new CType("EGLBoolean"), new JType("boolean"));
+    typeMapping.put(new CType("EGLenum"), new JType("int"));
+    typeMapping.put(new CType("EGLNativePixmapType"), new JType("int"));
+    typeMapping.put(new CType("EGLNativeWindowType"), new JType("int"));
+    typeMapping.put(new CType("EGLNativeDisplayType"), new JType("int"));
+    typeMapping.put(new CType("EGLClientBuffer"), new JType("int"));
+
+    // EGL nonprimitive types
+    typeMapping.put(new CType("EGLConfig"), new JType("EGLConfig", true, false));
+    typeMapping.put(new CType("EGLContext"), new JType("EGLContext", true, false));
+    typeMapping.put(new CType("EGLDisplay"), new JType("EGLDisplay", true, false));
+    typeMapping.put(new CType("EGLSurface"), new JType("EGLSurface", true, false));
+
+
     // Untyped pointers map to untyped Buffers
     typeMapping.put(new CType("GLvoid", true, true),
             new JType("java.nio.Buffer", true, false));
@@ -88,7 +104,7 @@
     arrayTypeMapping.put(new CType("char", false, true),
             new JType("byte", false, true));
     arrayTypeMapping.put(new CType("GLboolean", false, true),
-                 new JType("boolean", false, true));
+            new JType("boolean", false, true));
     arrayTypeMapping.put(new CType("GLenum", false, true), new JType("int", false, true));
     arrayTypeMapping.put(new CType("GLfixed", true, true), new JType("int", false, true));
     arrayTypeMapping.put(new CType("GLfixed", false, true), new JType("int", false, true));
@@ -103,6 +119,13 @@
     arrayTypeMapping.put(new CType("GLuint", true, true), new JType("int", false, true));
     arrayTypeMapping.put(new CType("GLintptr"), new JType("int", false, true));
     arrayTypeMapping.put(new CType("GLsizeiptr"), new JType("int", false, true));
+
+    //EGL typed pointers map to arrays + offsets
+    arrayTypeMapping.put(new CType("EGLint", false, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("EGLint", true, true), new JType("int", false, true));
+    arrayTypeMapping.put(new CType("EGLConfig", false, true), new JType("EGLConfig", true, true));
+    arrayTypeMapping.put(new CType("EGLConfig", true, true), new JType("EGLConfig", true, true));
+
     }
 
     public JType() {
@@ -158,6 +181,11 @@
         (baseType.indexOf("Buffer") != -1);
     }
 
+    public boolean isEGLHandle() {
+    return !isPrimitive() &&
+        (baseType.startsWith("EGL"));
+    }
+
     public static JType convert(CType ctype, boolean useArray) {
      JType javaType = null;
      if (useArray) {
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 9fa2b74..af98889 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -25,6 +25,8 @@
     static final boolean mUseCPlusPlus = true;
     protected boolean mUseContextPointer = true;
     protected boolean mUseStaticMethods = false;
+    protected boolean mUseSimpleMethodNames = false;
+    protected boolean mUseHideCommentForAPI = false;
     protected String mClassPathName;
     protected ParameterChecker mChecker;
     protected List<String> nativeRegistrations = new ArrayList<String>();
@@ -34,7 +36,9 @@
 
     public static String getJniName(JType jType) {
         String jniName = "";
-        if (jType.isClass()) {
+        if (jType.isEGLHandle()) {
+            return (jType.isArray() ? "[" : "" ) + "Landroid/opengl/" + jType.getBaseType() + ";";
+        } else if (jType.isClass()) {
             return "L" + jType.getBaseType() + ";";
         } else if (jType.isArray()) {
             jniName = "[";
@@ -63,7 +67,6 @@
         return jniName;
     }
 
-
     public void emitCode(CFunc cfunc, String original,
             PrintStream javaInterfaceStream,
             PrintStream javaImplStream,
@@ -96,6 +99,10 @@
             if (!duplicate) {
                 emitJniCode(jfunc, cStream);
             }
+            // Don't create IOBuffer versions of the EGL functions
+            if (cfunc.hasEGLHandleArg()) {
+                return;
+            }
         }
 
         jfunc = JFunc.convert(cfunc, false);
@@ -121,8 +128,13 @@
     }
 
     public void emitNativeDeclaration(JFunc jfunc, PrintStream out) {
-        out.println("    // C function " + jfunc.getCFunc().getOriginal());
-        out.println();
+        if (mUseHideCommentForAPI) {
+            out.println("    /* @hide C function " + jfunc.getCFunc().getOriginal() + " */");
+            out.println();
+        } else {
+            out.println("    // C function " + jfunc.getCFunc().getOriginal());
+            out.println();
+        }
 
         emitFunction(jfunc, out, true, false);
     }
@@ -197,15 +209,17 @@
                 out.println(iii + "}");
 
                 out.println(iii + "if (" + remaining + " < _needed) {");
-                if (emitExceptionCheck) {
-                    out.println(iii + indent + "_exception = 1;");
-                }
-                out.println(iii + indent + "jniThrowException(_env, " +
-                        "\"java/lang/IllegalArgumentException\", " +
-                        "\"" + (isBuffer ? "remaining()" : "length - " + offset) + " < needed\");");
+                out.println(iii + indent + "_exception = 1;");
+                out.println(iii + indent +
+                           "_exceptionType = \"java/lang/IllegalArgumentException\";");
+                out.println(iii + indent +
+                           "_exceptionMessage = \"" +
+                           (isBuffer ? "remaining()" : "length - " + offset) +
+                           " < needed\";");
                 out.println(iii + indent + "goto exit;");
-                needsExit = true;
                 out.println(iii + "}");
+
+                needsExit = true;
             }
 
     boolean isNullAllowed(CFunc cfunc) {
@@ -213,28 +227,70 @@
         int index = 1;
         if (checks != null) {
             while (index < checks.length) {
-                if (checks[index].equals("return")) {
-                    index += 2;
-                } else if (checks[index].startsWith("check")) {
-                    index += 3;
-                } else if (checks[index].equals("ifcheck")) {
-                    index += 5;
-                } else if (checks[index].equals("unsupported")) {
-                    index += 1;
-                } else if (checks[index].equals("requires")) {
-                    index += 2;
-                } else if (checks[index].equals("nullAllowed")) {
+                if (checks[index].equals("nullAllowed")) {
                     return true;
                 } else {
-                    System.out.println("Error: unknown keyword \"" +
-                                       checks[index] + "\"");
-                    System.exit(0);
+                    index = skipOneCheck(checks, index);
                 }
             }
         }
         return false;
     }
 
+    boolean hasCheckTest(CFunc cfunc) {
+        String[] checks = mChecker.getChecks(cfunc.getName());
+        int index = 1;
+        if (checks != null) {
+            while (index < checks.length) {
+                if (checks[index].startsWith("check")) {
+                    return true;
+                } else {
+                    index = skipOneCheck(checks, index);
+                }
+            }
+        }
+        return false;
+    }
+
+    boolean hasIfTest(CFunc cfunc) {
+        String[] checks = mChecker.getChecks(cfunc.getName());
+        int index = 1;
+        if (checks != null) {
+            while (index < checks.length) {
+                if (checks[index].startsWith("ifcheck")) {
+                    return true;
+                } else {
+                    index = skipOneCheck(checks, index);
+                }
+            }
+        }
+        return false;
+    }
+
+    int skipOneCheck(String[] checks, int index) {
+        if (checks[index].equals("return")) {
+            index += 2;
+        } else if (checks[index].startsWith("check")) {
+            index += 3;
+        } else if (checks[index].startsWith("sentinel")) {
+            index += 3;
+        } else if (checks[index].equals("ifcheck")) {
+            index += 5;
+        } else if (checks[index].equals("unsupported")) {
+            index += 1;
+        } else if (checks[index].equals("requires")) {
+            index += 2;
+        } else if (checks[index].equals("nullAllowed")) {
+            index += 1;
+        } else {
+            System.out.println("Error: unknown keyword \"" +
+                               checks[index] + "\"");
+            System.exit(0);
+        }
+
+        return index;
+    }
+
     String getErrorReturnValue(CFunc cfunc) {
         CType returnType = cfunc.getType();
         boolean isVoid = returnType.isVoid();
@@ -242,6 +298,10 @@
             return null;
         }
 
+        if (returnType.getBaseType().startsWith("EGL")) {
+            return "(" + returnType.getDeclaration() + ") 0";
+        }
+
         String[] checks = mChecker.getChecks(cfunc.getName());
 
         int index = 1;
@@ -249,20 +309,8 @@
             while (index < checks.length) {
                 if (checks[index].equals("return")) {
                     return checks[index + 1];
-                } else if (checks[index].startsWith("check")) {
-                    index += 3;
-                } else if (checks[index].equals("ifcheck")) {
-                    index += 5;
-                } else if (checks[index].equals("unsupported")) {
-                    index += 1;
-                } else if (checks[index].equals("requires")) {
-                    index += 2;
-                } else if (checks[index].equals("nullAllowed")) {
-                    index += 1;
                 } else {
-                    System.out.println("Error: unknown keyword \"" +
-                                       checks[index] + "\"");
-                    System.exit(0);
+                    index = skipOneCheck(checks, index);
                 }
             }
         }
@@ -277,20 +325,8 @@
             while (index < checks.length) {
                 if (checks[index].equals("unsupported")) {
                     return true;
-                } else if (checks[index].equals("requires")) {
-                    index += 2;
-                } else if (checks[index].equals("return")) {
-                    index += 2;
-                } else if (checks[index].startsWith("check")) {
-                    index += 3;
-                } else if (checks[index].equals("ifcheck")) {
-                    index += 5;
-                } else if (checks[index].equals("nullAllowed")) {
-                    index += 1;
                 } else {
-                    System.out.println("Error: unknown keyword \"" +
-                                       checks[index] + "\"");
-                    System.exit(0);
+                    index = skipOneCheck(checks, index);
                 }
             }
         }
@@ -302,22 +338,10 @@
         int index = 1;
         if (checks != null) {
             while (index < checks.length) {
-                if (checks[index].equals("unsupported")) {
-                    index += 1;
-                } else if (checks[index].equals("requires")) {
+                if (checks[index].equals("requires")) {
                     return checks[index+1];
-                } else if (checks[index].equals("return")) {
-                    index += 2;
-                } else if (checks[index].startsWith("check")) {
-                    index += 3;
-                } else if (checks[index].equals("ifcheck")) {
-                    index += 5;
-                } else if (checks[index].equals("nullAllowed")) {
-                    index += 1;
                 } else {
-                    System.out.println("Error: unknown keyword \"" +
-                                       checks[index] + "\"");
-                    System.exit(0);
+                    index = skipOneCheck(checks, index);
                 }
             }
         }
@@ -345,9 +369,7 @@
                         continue;
                     }
                     out.println(iii + "if (" + remaining + " < " + checks[index + 2] + ") {");
-                    if (emitExceptionCheck) {
-                        out.println(iii + indent + "_exception = 1;");
-                    }
+                    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
@@ -361,14 +383,19 @@
                             throw new RuntimeException("unknown exception abbreviation: " + abbr);
                         }
                     }
-                    out.println(iii + indent + "jniThrowException(_env, " +
-                            "\"" + exceptionClassName + "\", " +
-                            "\"" + (isBuffer ? "remaining()" : "length - " + offset) + " < " + checks[index + 2] + "\");");
+                    out.println(iii + indent +
+                                "_exceptionType = \""+exceptionClassName+"\";");
+                    out.println(iii + indent +
+                               "_exceptionMessage = \"" +
+                               (isBuffer ? "remaining()" : "length - " +
+                               offset) + " < " + checks[index + 2] +
+                               " < needed\";");
 
                     out.println(iii + indent + "goto exit;");
-                    needsExit = true;
                     out.println(iii + "}");
 
+                    needsExit = true;
+
                     index += 3;
                 } else if (checks[index].equals("ifcheck")) {
                     String[] matches = checks[index + 4].split(",");
@@ -388,21 +415,8 @@
 
                     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);
+                    index = skipOneCheck(checks, index);
                 }
             }
         }
@@ -412,6 +426,69 @@
         }
     }
 
+    void emitSentinelCheck(CFunc cfunc, String cname, PrintStream out,
+            boolean isBuffer, boolean emitExceptionCheck, String offset, String remaining, String iii) {
+
+        String[] checks = mChecker.getChecks(cfunc.getName());
+
+        int index = 1;
+        if (checks != null) {
+            while (index < checks.length) {
+                if (checks[index].startsWith("sentinel")) {
+                    if (cname != null && !cname.equals(checks[index + 1])) {
+                        index += 3;
+                        continue;
+                    }
+
+                    out.println(iii + cname + "_sentinel = false;");
+                    out.println(iii + "for (int i = " + remaining +
+                                " - 1; i >= 0; i--)  {");
+                    out.println(iii + indent + "if (" + cname +
+                                "[i] == " + checks[index + 2] + "){");
+                    out.println(iii + indent + indent +
+                                cname + "_sentinel = true;");
+                    out.println(iii + indent + indent + "break;");
+                    out.println(iii + indent + "}");
+                    out.println(iii + "}");
+                    out.println(iii +
+                                "if (" + cname + "_sentinel == false) {");
+                    out.println(iii + indent + "_exception = 1;");
+                    out.println(iii + indent +
+                                "_exceptionType = \"java/lang/IllegalArgumentException\";");
+                    out.println(iii + indent + "_exceptionMessage = \"" + cname +
+                                " must contain " + checks[index + 2] + "!\";");
+                    out.println(iii + indent + "goto exit;");
+                    out.println(iii + "}");
+
+                    needsExit = true;
+                    index += 3;
+                } else {
+                    index = skipOneCheck(checks, index);
+                }
+            }
+        }
+    }
+
+    void emitLocalVariablesForSentinel(CFunc cfunc, PrintStream out) {
+
+        String[] checks = mChecker.getChecks(cfunc.getName());
+
+        int index = 1;
+        if (checks != null) {
+            while (index < checks.length) {
+                if (checks[index].startsWith("sentinel")) {
+                    String cname = checks[index + 1];
+                    out.println(indent + "bool " + cname + "_sentinel = false;");
+
+                    index += 3;
+
+                } else {
+                    index = skipOneCheck(checks, index);
+                }
+            }
+        }
+    }
+
     boolean hasNonConstArg(JFunc jfunc, CFunc cfunc, List<Integer> nonPrimitiveArgs) {
         if (nonPrimitiveArgs.size() > 0) {
             for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
@@ -638,7 +715,7 @@
                 return "j" + baseType;
             }
         } else if (jType.isArray()) {
-            return "j" + baseType + "Array";
+            return jType.isClass() ? "jobjectArray" : "j" + baseType + "Array";
         } else {
             return "jobject";
         }
@@ -698,8 +775,10 @@
 
         // Append signature to function name
         String sig = getJniMangledName(signature).replace('.', '_').replace('/', '_');
-        out.print("__" + sig);
-        outName += "__" + sig;
+        if (!mUseSimpleMethodNames) {
+            out.print("__" + sig);
+            outName += "__" + sig;
+        }
 
         signature = signature.replace('.', '/');
         rsignature = rsignature.replace('.', '/');
@@ -734,11 +813,11 @@
         for (int i = 0; i < numArgs; i++) {
             out.print(", ");
             JType argType = jfunc.getArgType(i);
-            String suffix;
+            String suffix = "";
             if (!argType.isPrimitive()) {
                 if (argType.isArray()) {
                     suffix = "_ref";
-                } else {
+                } else if (argType.isBuffer()) {
                     suffix = "_buf";
                 }
                 nonPrimitiveArgs.add(new Integer(i));
@@ -748,9 +827,8 @@
                     bufferArgNames.add(cname);
                     numBufferArgs++;
                 }
-            } else {
-                suffix = "";
             }
+
             if (argType.isString()) {
                 stringArgs.add(new Integer(i));
             }
@@ -801,7 +879,14 @@
                         "    \"" + cfunc.getName() + "\");");
             if (!isVoid) {
                 String retval = getErrorReturnValue(cfunc);
-                out.println(indent + "return " + retval + ";");
+                if (cfunc.getType().isEGLHandle()) {
+                    String baseType = cfunc.getType().getBaseType().toLowerCase();
+                    out.println(indent +
+                                "return toEGLHandle(_env, " + baseType + "Class, " +
+                                baseType + "Constructor, " + retval + ");");
+                } else {
+                    out.println(indent + "return " + retval + ";");
+                }
             }
             out.println("}");
             out.println();
@@ -820,7 +905,14 @@
                 out.println(indent + indent + "    return;");
             } else {
                 String retval = getErrorReturnValue(cfunc);
-                out.println(indent + indent + "    return " + retval + ";");
+                if (cfunc.getType().isEGLHandle()) {
+                    String baseType = cfunc.getType().getBaseType().toLowerCase();
+                    out.println(indent +
+                                "return toEGLHandle(_env, " + baseType + "Class, " +
+                                baseType + "Constructor, " + retval + ");");
+                } else {
+                    out.println(indent + "return " + retval + ";");
+                }
             }
             out.println(indent + "}");
         }
@@ -830,14 +922,18 @@
         }
 
         boolean initializeReturnValue = stringArgs.size() > 0;
-
-        boolean emitExceptionCheck = (numArrays > 0 || numBuffers > 0 || numStrings > 0) &&
-            hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs);
+        boolean emitExceptionCheck = ((numArrays > 0 || numStrings > 0)
+                                             && (hasNonConstArg(jfunc, cfunc, nonPrimitiveArgs)
+                                                 || (cfunc.hasPointerArg() && numArrays > 0))
+                                         || hasCheckTest(cfunc)
+                                         || hasIfTest(cfunc))
+                                         || (stringArgs.size() > 0);
         // mChecker.getChecks(cfunc.getName()) != null
-
         // Emit an _exeption variable if there will be error checks
         if (emitExceptionCheck) {
             out.println(indent + "jint _exception = 0;");
+            out.println(indent + "const char * _exceptionType;");
+            out.println(indent + "const char * _exceptionMessage;");
         }
 
         // Emit a single _array or multiple _XXXArray variables
@@ -856,13 +952,49 @@
                             " _returnValue = " + retval + ";");
             } else if (initializeReturnValue) {
                 out.println(indent + returnType.getDeclaration() +
-                " _returnValue = 0;");
+                            " _returnValue = 0;");
             } else {
                 out.println(indent + returnType.getDeclaration() +
                             " _returnValue;");
             }
         }
 
+        // Emit local variable declarations for EGL Handles
+        //
+        // Example:
+        //
+        // EGLSurface surface_native = (EGLHandle)fromEGLHandle(_env, surfaceClass, surfaceConstructor, surface);
+        //
+        if (nonPrimitiveArgs.size() > 0) {
+            for (int i = 0; i < nonPrimitiveArgs.size(); i++) {
+                int idx = nonPrimitiveArgs.get(i).intValue();
+                int cIndex = jfunc.getArgCIndex(idx);
+                String cname = cfunc.getArgName(cIndex);
+
+                if (jfunc.getArgType(idx).isBuffer()
+                   || jfunc.getArgType(idx).isArray()
+                   || !jfunc.getArgType(idx).isEGLHandle())
+                    continue;
+
+                CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
+                String decl = type.getDeclaration();
+                out.println(indent +
+                            decl + " " + cname + "_native = (" +
+                            decl + ") fromEGLHandle(_env, " +
+                            type.getBaseType().toLowerCase() +
+                            "GetHandleID, " + jfunc.getArgName(idx) +
+                            ");");
+            }
+        }
+
+        // Emit local variable declarations for element/sentinel checks
+        //
+        // Example:
+        //
+        // bool attrib_list_sentinel_found = false;
+        //
+        emitLocalVariablesForSentinel(cfunc, out);
+
         // Emit local variable declarations for pointer arguments
         //
         // Example:
@@ -878,9 +1010,12 @@
                 int cIndex = jfunc.getArgCIndex(idx);
                 String cname = cfunc.getArgName(cIndex);
 
+                if (!jfunc.getArgType(idx).isBuffer() && !jfunc.getArgType(idx).isArray())
+                    continue;
+
                 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
                 String decl = type.getDeclaration();
-                if (jfunc.getArgType(idx).isArray()) {
+                if (jfunc.getArgType(idx).isArray() && !jfunc.getArgType(idx).isClass()) {
                     out.println(indent +
                                 decl +
                                 (decl.endsWith("*") ? "" : " ") +
@@ -892,10 +1027,10 @@
                 out.println(indent +
                             "jint " + remaining + ";");
                 out.println(indent +
-                            decl +
-                            (decl.endsWith("*") ? "" : " ") +
-                            jfunc.getArgName(idx) +
-                            " = (" + decl + ") 0;");
+                                decl +
+                                (decl.endsWith("*") ? "" : " ") +
+                                jfunc.getArgName(idx) +
+                                " = (" + decl + ") 0;");
             }
 
             out.println();
@@ -923,11 +1058,13 @@
 
                 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
                 String decl = type.getDeclaration();
-                out.println(indent + "if (!" + cname + ") {");
-                out.println(indent + "    jniThrowException(_env, " +
-                        "\"java/lang/IllegalArgumentException\", \"" + cname + " == null\");");
-                out.println(indent + "    goto exit;");
                 needsExit = true;
+                out.println(indent + "if (!" + cname + ") {");
+                out.println(indent + indent +
+                            "_exceptionType = \"java/lang/IllegalArgumentException\";");
+                out.println(indent + indent +
+                            "_exceptionMessage = \"" + cname + " == null\";");
+                out.println(indent + indent + "goto exit;");
                 out.println(indent + "}");
 
                 out.println(indent + "_native" + cname + " = _env->GetStringUTFChars(" + cname + ", 0);");
@@ -936,7 +1073,7 @@
             out.println();
         }
 
-        // Emit 'GetPrimitiveArrayCritical' for arrays
+        // Emit 'GetPrimitiveArrayCritical' for non-object arrays
         // Emit 'GetPointer' calls for Buffer pointers
         int bufArgIdx = 0;
         if (nonPrimitiveArgs.size() > 0) {
@@ -950,29 +1087,24 @@
                 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
                     "_" + cname + "Remaining";
 
-                if (jfunc.getArgType(idx).isArray()) {
-                    out.println(indent +
-                                "if (!" +
-                                cname +
-                                "_ref) {");
-                    if (emitExceptionCheck) {
-                        out.println(indent + indent + "_exception = 1;");
-                    }
-                    out.println(indent + "    jniThrowException(_env, " +
-                            "\"java/lang/IllegalArgumentException\", " +
-                            "\"" + cname + " == null\");");
-                    out.println(indent + "    goto exit;");
+                if (jfunc.getArgType(idx).isArray()
+                       && !jfunc.getArgType(idx).isEGLHandle()) {
                     needsExit = true;
+                    out.println(indent + "if (!" + cname + "_ref) {");
+                    out.println(indent + indent + "_exception = 1;");
+                    out.println(indent + indent +
+                                "_exceptionType = \"java/lang/IllegalArgumentException\";");
+                    out.println(indent + indent +
+                                "_exceptionMessage = \"" + cname +" == null\";");
+                    out.println(indent + indent + "goto exit;");
                     out.println(indent + "}");
-
                     out.println(indent + "if (" + offset + " < 0) {");
-                    if (emitExceptionCheck) {
-                        out.println(indent + indent + "_exception = 1;");
-                    }
-                    out.println(indent + "    jniThrowException(_env, " +
-                            "\"java/lang/IllegalArgumentException\", \"" + offset + " < 0\");");
-                    out.println(indent + "    goto exit;");
-                    needsExit = true;
+                    out.println(indent + indent + "_exception = 1;");
+                    out.println(indent + indent +
+                                "_exceptionType = \"java/lang/IllegalArgumentException\";");
+                    out.println(indent + indent +
+                                "_exceptionMessage = \"" + offset +" < 0\";");
+                    out.println(indent + indent + "goto exit;");
                     out.println(indent + "}");
 
                     out.println(indent + remaining + " = " +
@@ -997,10 +1129,44 @@
                                 jfunc.getArgName(idx) +
                                 "_ref, (jboolean *)0);");
                     out.println(indent +
-                                cname + " = " + cname + "_base + " + offset +
-                                ";");
+                                cname + " = " + cname + "_base + " + offset + ";");
+
+                    emitSentinelCheck(cfunc, cname, out, false,
+                                      emitExceptionCheck, offset,
+                                      remaining, indent);
                     out.println();
-                } else {
+                } else if (jfunc.getArgType(idx).isArray()
+                              && jfunc.getArgType(idx).isEGLHandle()) {
+                    needsExit = true;
+                    out.println(indent + "if (!" + cname + "_ref) {");
+                    out.println(indent + indent + "_exception = 1;");
+                    out.println(indent + indent +
+                                "_exceptionType = \"java/lang/IllegalArgumentException\";");
+                    out.println(indent + indent + "_exceptionMessage = \"" + cname +" == null\";");
+                    out.println(indent + indent + "goto exit;");
+                    out.println(indent + "}");
+                    out.println(indent + "if (" + offset + " < 0) {");
+                    out.println(indent + indent + "_exception = 1;");
+                    out.println(indent + indent +
+                                "_exceptionType = \"java/lang/IllegalArgumentException\";");
+                    out.println(indent + indent + "_exceptionMessage = \"" + offset +" < 0\";");
+                    out.println(indent + indent + "goto exit;");
+                    out.println(indent + "}");
+
+                    out.println(indent + remaining + " = " +
+                                    (mUseCPlusPlus ? "_env" : "(*_env)") +
+                                    "->GetArrayLength(" +
+                                    (mUseCPlusPlus ? "" : "_env, ") +
+                                    cname + "_ref) - " + offset + ";");
+                    emitNativeBoundsChecks(cfunc, cname, out, false,
+                                           emitExceptionCheck,
+                                           offset, remaining, "    ");
+                    out.println(indent +
+                                jfunc.getArgName(idx) + " = new " +
+                                cfunc.getArgType(cIndex).getBaseType() +
+                               "["+ remaining + "];");
+                    out.println();
+                } else if (jfunc.getArgType(idx).isBuffer()) {
                     String array = numBufferArgs <= 1 ? "_array" :
                         "_" + bufferArgNames.get(bufArgIdx++) + "Array";
 
@@ -1019,7 +1185,7 @@
                                 cname + "_buf);");
                         String iii = "    ";
                         out.println(iii + indent + "if ( ! " + cname + " ) {");
-                        out.println(iii + iii + indent + "return;");
+                        out.println(iii + indent + indent + "return;");
                         out.println(iii + indent + "}");
                     } else {
                         out.println(indent +
@@ -1075,18 +1241,23 @@
             for (int i = 0; i < numArgs; i++) {
                 String typecast;
                 if (i == numArgs - 1 && isVBOPointerFunc) {
-                    typecast = "const GLvoid *";
+                    typecast = "(const GLvoid *)";
                 } else {
-                    typecast = cfunc.getArgType(i).getDeclaration();
+                    typecast = "(" + cfunc.getArgType(i).getDeclaration() + ")";
                 }
                 out.print(indent + indent +
-                          "(" +
-                          typecast +
-                          ")");
+                          typecast);
+
                 if (cfunc.getArgType(i).isConstCharPointer()) {
                     out.print("_native");
                 }
-                out.print(cfunc.getArgName(i));
+
+		if (cfunc.getArgType(i).isEGLHandle() &&
+                    !cfunc.getArgType(i).isPointer()){
+                    out.print(cfunc.getArgName(i)+"_native");
+                } else {
+                    out.print(cfunc.getArgName(i));
+                }
 
                 if (i == numArgs - 1) {
                     if (isPointerFunc) {
@@ -1114,7 +1285,7 @@
                 int idx = nonPrimitiveArgs.get(i).intValue();
 
                 int cIndex = jfunc.getArgCIndex(idx);
-                if (jfunc.getArgType(idx).isArray()) {
+                if (jfunc.getArgType(idx).isArray() && !jfunc.getArgType(idx).isClass()) {
 
                     // If the argument is 'const', GL will not write to it.
                     // In this case, we can use the 'JNI_ABORT' flag to avoid
@@ -1130,8 +1301,7 @@
                                 "_base,");
                     out.println(indent + indent + indent +
                                 (cfunc.getArgType(cIndex).isConst() ?
-                                 "JNI_ABORT" :
-                                 "_exception ? JNI_ABORT: 0") +
+                                 "JNI_ABORT" : "_exception ? JNI_ABORT: 0" ) +
                                 ");");
                     out.println(indent + "}");
                 } else if (jfunc.getArgType(idx).isBuffer()) {
@@ -1144,8 +1314,8 @@
                                     cfunc.getArgName(cIndex) +
                                     ", " +
                                     (cfunc.getArgType(cIndex).isConst() ?
-                                     "JNI_FALSE" : "_exception ? JNI_FALSE :" +
-                                             " JNI_TRUE") +
+                                     "JNI_FALSE" : (emitExceptionCheck ?
+                                     "_exception ? JNI_FALSE : JNI_TRUE" : "JNI_TRUE")) +
                                     ");");
                         out.println(indent + "}");
                     }
@@ -1168,9 +1338,60 @@
             out.println();
         }
 
+        // Copy results back to java arrays
+       if (nonPrimitiveArgs.size() > 0) {
+            for (int i = nonPrimitiveArgs.size() - 1; i >= 0; i--) {
+                int idx = nonPrimitiveArgs.get(i).intValue();
+                int cIndex = jfunc.getArgCIndex(idx);
+                String baseType = cfunc.getArgType(cIndex).getBaseType().toLowerCase();
+                if (jfunc.getArgType(idx).isArray() && jfunc.getArgType(idx).isClass()) {
+                    remaining  = ((numArrays + numBuffers) <= 1) ? "_remaining" :
+                                     "_" + cfunc.getArgName(cIndex) + "Remaining";
+                    offset = numArrays <= 1 ? "offset" : cfunc.getArgName(cIndex) + "Offset";
+                    out.println(indent +
+                                "if (" + jfunc.getArgName(idx) + ") {");
+                    out.println(indent + indent +
+                                "for (int i = 0; i < " + remaining + "; i++) {");
+                    out.println(indent + indent + indent +
+                                "jobject " + cfunc.getArgName(cIndex) +
+                                "_new = toEGLHandle(_env, " + baseType +
+                                "Class, " + baseType + "Constructor, " +
+                                cfunc.getArgName(cIndex) + "[i]);");
+                    out.println(indent + indent + indent +
+                                (mUseCPlusPlus ? "_env" : "(*_env)") +
+                                "->SetObjectArrayElement(" +
+                                (mUseCPlusPlus ? "" : "_env, ") +
+                                cfunc.getArgName(cIndex) +
+                                "_ref, i + " + offset + ", " +
+                                cfunc.getArgName(cIndex) + "_new);");
+                    out.println(indent + indent + "}");
+                    out.println(indent + indent +
+                                "delete[] " + jfunc.getArgName(idx) + ";");
+                    out.println(indent + "}");
+                }
+            }
+        }
+
+
+        // Throw exception if there is one
+        if (emitExceptionCheck) {
+            out.println(indent + "if (_exception) {");
+            out.println(indent + indent +
+                        "jniThrowException(_env, _exceptionType, _exceptionMessage);");
+            out.println(indent + "}");
+
+        }
+
 
         if (!isVoid) {
-            out.println(indent + "return _returnValue;");
+            if (cfunc.getType().isEGLHandle()) {
+                String baseType = cfunc.getType().getBaseType().toLowerCase();
+                out.println(indent +
+                            "return toEGLHandle(_env, " + baseType + "Class, " +
+                            baseType + "Constructor, _returnValue);");
+            } else {
+                out.println(indent + "return _returnValue;");
+            }
         }
 
         out.println("}");
diff --git a/opengl/tools/glgen/static/egl/EGLConfig.java b/opengl/tools/glgen/static/egl/EGLConfig.java
new file mode 100644
index 0000000..d9aebfc
--- /dev/null
+++ b/opengl/tools/glgen/static/egl/EGLConfig.java
@@ -0,0 +1,41 @@
+/*
+**
+** Copyright 2012, 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.opengl;
+
+/**
+ * @hide
+ */
+public class EGLConfig extends EGLObjectHandle {
+    public EGLConfig(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLConfig that = (EGLConfig) o;
+        return getHandle() == that.getHandle();
+    }
+
+    @Override
+    public int hashCode() {
+        return getHandle();
+    }
+}
diff --git a/opengl/tools/glgen/static/egl/EGLContext.java b/opengl/tools/glgen/static/egl/EGLContext.java
new file mode 100644
index 0000000..7b194f3
--- /dev/null
+++ b/opengl/tools/glgen/static/egl/EGLContext.java
@@ -0,0 +1,41 @@
+/*
+**
+** Copyright 2012, 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.opengl;
+
+/**
+ * @hide
+ */
+public class EGLContext extends EGLObjectHandle {
+    public EGLContext(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLContext that = (EGLContext) o;
+        return getHandle() == that.getHandle();
+    }
+
+    @Override
+    public int hashCode() {
+        return getHandle();
+    }
+}
diff --git a/opengl/tools/glgen/static/egl/EGLDisplay.java b/opengl/tools/glgen/static/egl/EGLDisplay.java
new file mode 100644
index 0000000..a090cf0
--- /dev/null
+++ b/opengl/tools/glgen/static/egl/EGLDisplay.java
@@ -0,0 +1,41 @@
+/*
+**
+** Copyright 2012, 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.opengl;
+
+/**
+ * @hide
+ */
+public class EGLDisplay extends EGLObjectHandle {
+    public EGLDisplay(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLDisplay that = (EGLDisplay) o;
+        return getHandle() == that.getHandle();
+    }
+
+    @Override
+    public int hashCode() {
+        return getHandle();
+    }
+}
diff --git a/opengl/tools/glgen/static/egl/EGLObjectHandle.java b/opengl/tools/glgen/static/egl/EGLObjectHandle.java
new file mode 100644
index 0000000..01f9bd4
--- /dev/null
+++ b/opengl/tools/glgen/static/egl/EGLObjectHandle.java
@@ -0,0 +1,33 @@
+/*
+**
+** Copyright 2012, 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.opengl;
+
+/**
+ * @hide
+ */
+public abstract class EGLObjectHandle {
+    private final int mHandle;
+
+    public EGLObjectHandle(int handle) {
+        mHandle = handle;
+    }
+
+    public int getHandle() {
+        return mHandle;
+    }
+}
diff --git a/opengl/tools/glgen/static/egl/EGLSurface.java b/opengl/tools/glgen/static/egl/EGLSurface.java
new file mode 100644
index 0000000..4800a64
--- /dev/null
+++ b/opengl/tools/glgen/static/egl/EGLSurface.java
@@ -0,0 +1,41 @@
+/*
+**
+** Copyright 2012, 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.opengl;
+
+/**
+ * @hide
+ */
+public class EGLSurface extends EGLObjectHandle {
+    public EGLSurface(int handle) {
+        super(handle);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EGLSurface that = (EGLSurface) o;
+        return getHandle() == that.getHandle();
+    }
+
+    @Override
+    public int hashCode() {
+        return getHandle();
+    }
+}
diff --git a/opengl/tools/glgen/stubs/egl/EGL14Header.java-if b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if
new file mode 100644
index 0000000..9330c99
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/EGL14Header.java-if
@@ -0,0 +1,151 @@
+**
+** Copyright 2012, 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
+
+package android.opengl;
+
+import android.graphics.SurfaceTexture;
+import android.view.Surface;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+
+
+/**
+* @hide
+*/
+public class EGL14 {
+
+public static final int EGL_DEFAULT_DISPLAY            = 0;
+public static EGLContext EGL_NO_CONTEXT                = null;
+public static EGLDisplay EGL_NO_DISPLAY                = null;
+public static EGLSurface EGL_NO_SURFACE                = null;
+
+public static final int EGL_FALSE                          = 0;
+public static final int EGL_TRUE                           = 1;
+public static final int EGL_SUCCESS                        = 0x3000;
+public static final int EGL_NOT_INITIALIZED                = 0x3001;
+public static final int EGL_BAD_ACCESS                     = 0x3002;
+public static final int EGL_BAD_ALLOC                      = 0x3003;
+public static final int EGL_BAD_ATTRIBUTE                  = 0x3004;
+public static final int EGL_BAD_CONFIG                     = 0x3005;
+public static final int EGL_BAD_CONTEXT                    = 0x3006;
+public static final int EGL_BAD_CURRENT_SURFACE            = 0x3007;
+public static final int EGL_BAD_DISPLAY                    = 0x3008;
+public static final int EGL_BAD_MATCH                      = 0x3009;
+public static final int EGL_BAD_NATIVE_PIXMAP              = 0x300A;
+public static final int EGL_BAD_NATIVE_WINDOW              = 0x300B;
+public static final int EGL_BAD_PARAMETER                  = 0x300C;
+public static final int EGL_BAD_SURFACE                    = 0x300D;
+public static final int EGL_CONTEXT_LOST                   = 0x300E;
+public static final int EGL_BUFFER_SIZE                    = 0x3020;
+public static final int EGL_ALPHA_SIZE                     = 0x3021;
+public static final int EGL_BLUE_SIZE                      = 0x3022;
+public static final int EGL_GREEN_SIZE                     = 0x3023;
+public static final int EGL_RED_SIZE                       = 0x3024;
+public static final int EGL_DEPTH_SIZE                     = 0x3025;
+public static final int EGL_STENCIL_SIZE                   = 0x3026;
+public static final int EGL_CONFIG_CAVEAT                  = 0x3027;
+public static final int EGL_CONFIG_ID                      = 0x3028;
+public static final int EGL_LEVEL                          = 0x3029;
+public static final int EGL_MAX_PBUFFER_HEIGHT             = 0x302A;
+public static final int EGL_MAX_PBUFFER_PIXELS             = 0x302B;
+public static final int EGL_MAX_PBUFFER_WIDTH              = 0x302C;
+public static final int EGL_NATIVE_RENDERABLE              = 0x302D;
+public static final int EGL_NATIVE_VISUAL_ID               = 0x302E;
+public static final int EGL_NATIVE_VISUAL_TYPE             = 0x302F;
+public static final int EGL_SAMPLES                        = 0x3031;
+public static final int EGL_SAMPLE_BUFFERS                 = 0x3032;
+public static final int EGL_SURFACE_TYPE                   = 0x3033;
+public static final int EGL_TRANSPARENT_TYPE               = 0x3034;
+public static final int EGL_TRANSPARENT_BLUE_VALUE         = 0x3035;
+public static final int EGL_TRANSPARENT_GREEN_VALUE        = 0x3036;
+public static final int EGL_TRANSPARENT_RED_VALUE          = 0x3037;
+public static final int EGL_NONE                           = 0x3038;
+public static final int EGL_BIND_TO_TEXTURE_RGB            = 0x3039;
+public static final int EGL_BIND_TO_TEXTURE_RGBA           = 0x303A;
+public static final int EGL_MIN_SWAP_INTERVAL              = 0x303B;
+public static final int EGL_MAX_SWAP_INTERVAL              = 0x303C;
+public static final int EGL_LUMINANCE_SIZE                 = 0x303D;
+public static final int EGL_ALPHA_MASK_SIZE                = 0x303E;
+public static final int EGL_COLOR_BUFFER_TYPE              = 0x303F;
+public static final int EGL_RENDERABLE_TYPE                = 0x3040;
+public static final int EGL_MATCH_NATIVE_PIXMAP            = 0x3041;
+public static final int EGL_CONFORMANT                     = 0x3042;
+public static final int EGL_SLOW_CONFIG                    = 0x3050;
+public static final int EGL_NON_CONFORMANT_CONFIG          = 0x3051;
+public static final int EGL_TRANSPARENT_RGB                = 0x3052;
+public static final int EGL_RGB_BUFFER                     = 0x308E;
+public static final int EGL_LUMINANCE_BUFFER               = 0x308F;
+public static final int EGL_NO_TEXTURE                     = 0x305C;
+public static final int EGL_TEXTURE_RGB                    = 0x305D;
+public static final int EGL_TEXTURE_RGBA                   = 0x305E;
+public static final int EGL_TEXTURE_2D                     = 0x305F;
+public static final int EGL_PBUFFER_BIT                    = 0x0001;
+public static final int EGL_PIXMAP_BIT                     = 0x0002;
+public static final int EGL_WINDOW_BIT                     = 0x0004;
+public static final int EGL_VG_COLORSPACE_LINEAR_BIT       = 0x0020;
+public static final int EGL_VG_ALPHA_FORMAT_PRE_BIT        = 0x0040;
+public static final int EGL_MULTISAMPLE_RESOLVE_BOX_BIT    = 0x0200;
+public static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT    = 0x0400;
+public static final int EGL_OPENGL_ES_BIT                  = 0x0001;
+public static final int EGL_OPENVG_BIT                     = 0x0002;
+public static final int EGL_OPENGL_ES2_BIT                 = 0x0004;
+public static final int EGL_OPENGL_BIT                     = 0x0008;
+public static final int EGL_VENDOR                         = 0x3053;
+public static final int EGL_VERSION                        = 0x3054;
+public static final int EGL_EXTENSIONS                     = 0x3055;
+public static final int EGL_CLIENT_APIS                    = 0x308D;
+public static final int EGL_HEIGHT                         = 0x3056;
+public static final int EGL_WIDTH                          = 0x3057;
+public static final int EGL_LARGEST_PBUFFER                = 0x3058;
+public static final int EGL_TEXTURE_FORMAT                 = 0x3080;
+public static final int EGL_TEXTURE_TARGET                 = 0x3081;
+public static final int EGL_MIPMAP_TEXTURE                 = 0x3082;
+public static final int EGL_MIPMAP_LEVEL                   = 0x3083;
+public static final int EGL_RENDER_BUFFER                  = 0x3086;
+public static final int EGL_VG_COLORSPACE                  = 0x3087;
+public static final int EGL_VG_ALPHA_FORMAT                = 0x3088;
+public static final int EGL_HORIZONTAL_RESOLUTION          = 0x3090;
+public static final int EGL_VERTICAL_RESOLUTION            = 0x3091;
+public static final int EGL_PIXEL_ASPECT_RATIO             = 0x3092;
+public static final int EGL_SWAP_BEHAVIOR                  = 0x3093;
+public static final int EGL_MULTISAMPLE_RESOLVE            = 0x3099;
+public static final int EGL_BACK_BUFFER                    = 0x3084;
+public static final int EGL_SINGLE_BUFFER                  = 0x3085;
+public static final int EGL_VG_COLORSPACE_sRGB             = 0x3089;
+public static final int EGL_VG_COLORSPACE_LINEAR           = 0x308A;
+public static final int EGL_VG_ALPHA_FORMAT_NONPRE         = 0x308B;
+public static final int EGL_VG_ALPHA_FORMAT_PRE            = 0x308C;
+public static final int EGL_DISPLAY_SCALING                = 10000;
+public static final int EGL_BUFFER_PRESERVED               = 0x3094;
+public static final int EGL_BUFFER_DESTROYED               = 0x3095;
+public static final int EGL_OPENVG_IMAGE                   = 0x3096;
+public static final int EGL_CONTEXT_CLIENT_TYPE            = 0x3097;
+public static final int EGL_CONTEXT_CLIENT_VERSION         = 0x3098;
+public static final int EGL_MULTISAMPLE_RESOLVE_DEFAULT    = 0x309A;
+public static final int EGL_MULTISAMPLE_RESOLVE_BOX        = 0x309B;
+public static final int EGL_OPENGL_ES_API                  = 0x30A0;
+public static final int EGL_OPENVG_API                     = 0x30A1;
+public static final int EGL_OPENGL_API                     = 0x30A2;
+public static final int EGL_DRAW                           = 0x3059;
+public static final int EGL_READ                           = 0x305A;
+public static final int EGL_CORE_NATIVE_ENGINE             = 0x305B;
+
+    native private static void _nativeClassInit();
+    static {
+        _nativeClassInit();
+    }
diff --git a/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
new file mode 100644
index 0000000..7904ac7
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/EGL14cHeader.cpp
@@ -0,0 +1,132 @@
+**
+** Copyright 2012, 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
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
+#include <utils/misc.h>
+
+#include <assert.h>
+#include <EGL/egl.h>
+
+#include <gui/Surface.h>
+#include <gui/SurfaceTexture.h>
+#include <gui/SurfaceTextureClient.h>
+
+#include <ui/ANativeObjectBase.h>
+
+static int initialized = 0;
+
+static jclass egldisplayClass;
+static jclass eglcontextClass;
+static jclass eglsurfaceClass;
+static jclass eglconfigClass;
+
+static jmethodID egldisplayGetHandleID;
+static jmethodID eglcontextGetHandleID;
+static jmethodID eglsurfaceGetHandleID;
+static jmethodID eglconfigGetHandleID;
+
+static jmethodID egldisplayConstructor;
+static jmethodID eglcontextConstructor;
+static jmethodID eglsurfaceConstructor;
+static jmethodID eglconfigConstructor;
+
+static jobject eglNoContextObject;
+static jobject eglNoDisplayObject;
+static jobject eglNoSurfaceObject;
+
+
+
+/* Cache method IDs each time the class is loaded. */
+
+static void
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
+{
+    jclass egldisplayClassLocal = _env->FindClass("android/opengl/EGLDisplay");
+    egldisplayClass = (jclass) _env->NewGlobalRef(egldisplayClassLocal);
+    jclass eglcontextClassLocal = _env->FindClass("android/opengl/EGLContext");
+    eglcontextClass = (jclass) _env->NewGlobalRef(eglcontextClassLocal);
+    jclass eglsurfaceClassLocal = _env->FindClass("android/opengl/EGLSurface");
+    eglsurfaceClass = (jclass) _env->NewGlobalRef(eglsurfaceClassLocal);
+    jclass eglconfigClassLocal = _env->FindClass("android/opengl/EGLConfig");
+    eglconfigClass = (jclass) _env->NewGlobalRef(eglconfigClassLocal);
+
+    egldisplayGetHandleID = _env->GetMethodID(egldisplayClass, "getHandle", "()I");
+    eglcontextGetHandleID = _env->GetMethodID(eglcontextClass, "getHandle", "()I");
+    eglsurfaceGetHandleID = _env->GetMethodID(eglsurfaceClass, "getHandle", "()I");
+    eglconfigGetHandleID = _env->GetMethodID(eglconfigClass, "getHandle", "()I");
+
+
+    egldisplayConstructor = _env->GetMethodID(egldisplayClass, "<init>", "(I)V");
+    eglcontextConstructor = _env->GetMethodID(eglcontextClass, "<init>", "(I)V");
+    eglsurfaceConstructor = _env->GetMethodID(eglsurfaceClass, "<init>", "(I)V");
+    eglconfigConstructor = _env->GetMethodID(eglconfigClass, "<init>", "(I)V");
+
+    jobject localeglNoContextObject = _env->NewObject(eglcontextClass, eglcontextConstructor, (jint)EGL_NO_CONTEXT);
+    eglNoContextObject = _env->NewGlobalRef(localeglNoContextObject);
+    jobject localeglNoDisplayObject = _env->NewObject(egldisplayClass, egldisplayConstructor, (jint)EGL_NO_DISPLAY);
+    eglNoDisplayObject = _env->NewGlobalRef(localeglNoDisplayObject);
+    jobject localeglNoSurfaceObject = _env->NewObject(eglsurfaceClass, eglsurfaceConstructor, (jint)EGL_NO_SURFACE);
+    eglNoSurfaceObject = _env->NewGlobalRef(localeglNoSurfaceObject);
+
+
+    jclass eglClass = _env->FindClass("android/opengl/EGL14");
+    jfieldID noContextFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_CONTEXT", "Landroid/opengl/EGLContext;");
+    _env->SetStaticObjectField(eglClass, noContextFieldID, eglNoContextObject);
+
+    jfieldID noDisplayFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_DISPLAY", "Landroid/opengl/EGLDisplay;");
+    _env->SetStaticObjectField(eglClass, noDisplayFieldID, eglNoDisplayObject);
+
+    jfieldID noSurfaceFieldID = _env->GetStaticFieldID(eglClass, "EGL_NO_SURFACE", "Landroid/opengl/EGLSurface;");
+    _env->SetStaticObjectField(eglClass, noSurfaceFieldID, eglNoSurfaceObject);
+}
+
+static void *
+fromEGLHandle(JNIEnv *_env, jmethodID mid, jobject obj) {
+    if (obj == NULL){
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Object is set to null.");
+    }
+
+    return (void*) (_env->CallIntMethod(obj, mid));
+}
+
+static jobject
+toEGLHandle(JNIEnv *_env, jclass cls, jmethodID con, void * handle) {
+    if (cls == eglcontextClass &&
+       (EGLContext)handle == EGL_NO_CONTEXT) {
+           return eglNoContextObject;
+    }
+
+    if (cls == egldisplayClass &&
+       (EGLDisplay)handle == EGL_NO_DISPLAY) {
+           return eglNoDisplayObject;
+    }
+
+    if (cls == eglsurfaceClass &&
+       (EGLSurface)handle == EGL_NO_SURFACE) {
+           return eglNoSurfaceObject;
+    }
+
+    return _env->NewObject(cls, con, (jint)handle);
+}
+
+// --------------------------------------------------------------------------
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp
new file mode 100644
index 0000000..610cde5
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp
@@ -0,0 +1,154 @@
+/* EGLSurface eglCreateWindowSurface ( EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list ) */
+static jobject
+android_eglCreateWindowSurface
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject win, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = "";
+    const char * _exceptionMessage = "";
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    int attrib_list_sentinel = 0;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+    android::sp<ANativeWindow> window;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    if (win == NULL) {
+not_valid_surface:
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface";
+        goto exit;
+    }
+
+    window = android::android_Surface_getNativeWindow(_env, win);
+
+    if (window == NULL)
+        goto not_valid_surface;
+
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = 0;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (*((EGLint*)(attrib_list + i)) == EGL_NONE){
+            attrib_list_sentinel = 1;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreateWindowSurface(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLNativeWindowType)window.get(),
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
+
+/* EGLSurface eglCreateWindowSurface ( EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list ) */
+static jobject
+android_eglCreateWindowSurfaceTexture
+  (JNIEnv *_env, jobject _this, jobject dpy, jobject config, jobject win, jintArray attrib_list_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = "";
+    const char * _exceptionMessage = "";
+    EGLSurface _returnValue = (EGLSurface) 0;
+    EGLDisplay dpy_native = (EGLDisplay) fromEGLHandle(_env, egldisplayGetHandleID, dpy);
+    EGLConfig config_native = (EGLConfig) fromEGLHandle(_env, eglconfigGetHandleID, config);
+    int attrib_list_sentinel = 0;
+    EGLint *attrib_list_base = (EGLint *) 0;
+    jint _remaining;
+    EGLint *attrib_list = (EGLint *) 0;
+    android::sp<ANativeWindow> window;
+    android::sp<android::SurfaceTexture> surfaceTexture;
+
+    if (!attrib_list_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    if (win == NULL) {
+not_valid_surface:
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface";
+        goto exit;
+    }
+    surfaceTexture = android::SurfaceTexture_getSurfaceTexture(_env, win);
+    window = new android::SurfaceTextureClient(surfaceTexture);
+
+    if (window == NULL)
+        goto not_valid_surface;
+
+    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+    attrib_list_base = (EGLint *)
+        _env->GetPrimitiveArrayCritical(attrib_list_ref, (jboolean *)0);
+    attrib_list = attrib_list_base + offset;
+    attrib_list_sentinel = 0;
+    for (int i = _remaining - 1; i >= 0; i--)  {
+        if (*((EGLint*)(attrib_list + i)) == EGL_NONE){
+            attrib_list_sentinel = 1;
+            break;
+        }
+    }
+    if (attrib_list_sentinel == 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "attrib_list must contain EGL_NONE!";
+        goto exit;
+    }
+
+    _returnValue = eglCreateWindowSurface(
+        (EGLDisplay)dpy_native,
+        (EGLConfig)config_native,
+        (EGLNativeWindowType)window.get(),
+        (EGLint *)attrib_list
+    );
+
+exit:
+    if (attrib_list_base) {
+        _env->ReleasePrimitiveArrayCritical(attrib_list_ref, attrib_list_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return toEGLHandle(_env, eglsurfaceClass, eglsurfaceConstructor, _returnValue);
+}
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.java b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.java
new file mode 100644
index 0000000..e42334e
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.java
@@ -0,0 +1,48 @@
+    // C function EGLSurface eglCreateWindowSurface ( EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list )
+
+    private static native EGLSurface _eglCreateWindowSurface(
+        EGLDisplay dpy,
+        EGLConfig config,
+        Object win,
+        int[] attrib_list,
+        int offset
+    );
+
+    private static native EGLSurface _eglCreateWindowSurfaceTexture(
+        EGLDisplay dpy,
+        EGLConfig config,
+        Object win,
+        int[] attrib_list,
+        int offset
+    );
+
+    public static EGLSurface eglCreateWindowSurface(EGLDisplay dpy,
+        EGLConfig config,
+        Object win,
+        int[] attrib_list,
+        int offset
+    ){
+        Surface sur = null;
+        if (win instanceof SurfaceView) {
+            SurfaceView surfaceView = (SurfaceView)win;
+            sur = surfaceView.getHolder().getSurface();
+        } else if (win instanceof SurfaceHolder) {
+            SurfaceHolder holder = (SurfaceHolder)win;
+            sur = holder.getSurface();
+        }
+
+        EGLSurface surface;
+        if (sur != null) {
+            surface = _eglCreateWindowSurface(dpy, config, sur, attrib_list, offset);
+        } else if (win instanceof SurfaceTexture) {
+            surface = _eglCreateWindowSurfaceTexture(dpy, config,
+                    win, attrib_list, offset);
+        } else {
+            throw new java.lang.UnsupportedOperationException(
+                "eglCreateWindowSurface() can only be called with an instance of " +
+                "SurfaceView, SurfaceTexture or SurfaceHolder at the moment, " +
+                "this will be fixed later.");
+        }
+
+        return surface;
+    }
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.nativeReg b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.nativeReg
new file mode 100644
index 0000000..c37d05b
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.nativeReg
@@ -0,0 +1,2 @@
+{"_eglCreateWindowSurface", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/lang/Object;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreateWindowSurface },
+{"_eglCreateWindowSurfaceTexture", "(Landroid/opengl/EGLDisplay;Landroid/opengl/EGLConfig;Ljava/lang/Object;[II)Landroid/opengl/EGLSurface;", (void *) android_eglCreateWindowSurfaceTexture },
diff --git a/opengl/tools/glgen/stubs/egl/eglQueryString.cpp b/opengl/tools/glgen/stubs/egl/eglQueryString.cpp
new file mode 100644
index 0000000..625dad7
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglQueryString.cpp
@@ -0,0 +1,10 @@
+/* const char * eglQueryString ( EGLDisplay dpy, EGLint name ) */
+static jstring
+android_eglQueryString__Landroind_opengl_EGLDisplay_2I
+  (JNIEnv *_env, jobject _this, jobject dpy, jint name) {
+    const char* chars = (const char*) eglQueryString(
+        (EGLDisplay)fromEGLHandle(_env, egldisplayGetHandleID, dpy),
+        (EGLint)name
+    );
+    return _env->NewStringUTF(chars);
+}
diff --git a/opengl/tools/glgen/stubs/egl/eglQueryString.java b/opengl/tools/glgen/stubs/egl/eglQueryString.java
new file mode 100644
index 0000000..f5d5a38
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglQueryString.java
@@ -0,0 +1,6 @@
+    // C function const char * eglQueryString ( EGLDisplay dpy, EGLint name )
+
+    public static native String eglQueryString(
+        EGLDisplay dpy,
+        int name
+    );
diff --git a/opengl/tools/glgen/stubs/egl/eglQueryString.nativeReg b/opengl/tools/glgen/stubs/egl/eglQueryString.nativeReg
new file mode 100644
index 0000000..8276cdb
--- /dev/null
+++ b/opengl/tools/glgen/stubs/egl/eglQueryString.nativeReg
@@ -0,0 +1 @@
+{"eglQueryString", "(Landroid/opengl/EGLDisplay;I)Ljava/lang/String;", (void *) android_eglQueryString__Landroind_opengl_EGLDisplay_2I },

diff --git a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
index cd730aa..e3aea76 100644
--- a/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
+++ b/opengl/tools/glgen/stubs/jsr239/GLImplHeader.java-impl
@@ -22,6 +22,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.os.Build;
+import android.os.UserId;
 import android.util.Log;
 
 import java.nio.Buffer;
@@ -66,7 +67,7 @@
         int version = 0;
         IPackageManager pm = AppGlobals.getPackageManager();
         try {
-            ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0);
+            ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0, UserId.myUserId());
             if (applicationInfo != null) {
                 version = applicationInfo.targetSdkVersion;
             }