Merge "Move setTint into Drawable, unhide getDirtyBounds on Drawable"
diff --git a/Android.mk b/Android.mk
index 4f50dac..d165595 100644
--- a/Android.mk
+++ b/Android.mk
@@ -159,6 +159,7 @@
 	core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl \
 	core/java/android/hardware/usb/IUsbManager.aidl \
 	core/java/android/net/IConnectivityManager.aidl \
+	core/java/android/net/IEthernetManager.aidl \
 	core/java/android/net/INetworkManagementEventObserver.aidl \
 	core/java/android/net/INetworkPolicyListener.aidl \
 	core/java/android/net/INetworkPolicyManager.aidl \
diff --git a/api/current.txt b/api/current.txt
index 6ce2d55..c38a82f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4452,9 +4452,11 @@
     field public static final int DEFAULT_LIGHTS = 4; // 0x4
     field public static final int DEFAULT_SOUND = 1; // 0x1
     field public static final int DEFAULT_VIBRATE = 2; // 0x2
+    field public static final java.lang.String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
     field public static final java.lang.String EXTRA_INFO_TEXT = "android.infoText";
     field public static final java.lang.String EXTRA_LARGE_ICON = "android.largeIcon";
     field public static final java.lang.String EXTRA_LARGE_ICON_BIG = "android.largeIcon.big";
+    field public static final java.lang.String EXTRA_MEDIA_SESSION = "android.mediaSession";
     field public static final java.lang.String EXTRA_PEOPLE = "android.people";
     field public static final java.lang.String EXTRA_PICTURE = "android.picture";
     field public static final java.lang.String EXTRA_PROGRESS = "android.progress";
@@ -4623,6 +4625,14 @@
     method public android.app.Notification.InboxStyle setSummaryText(java.lang.CharSequence);
   }
 
+  public static class Notification.MediaStyle extends android.app.Notification.Style {
+    ctor public Notification.MediaStyle();
+    ctor public Notification.MediaStyle(android.app.Notification.Builder);
+    method public android.app.Notification buildStyled(android.app.Notification);
+    method public android.app.Notification.MediaStyle setMediaSession(android.media.session.MediaSessionToken);
+    method public android.app.Notification.MediaStyle setShowActionsInCompactView(int...);
+  }
+
   public static abstract class Notification.Style {
     ctor public Notification.Style();
     method public android.app.Notification build();
@@ -12860,7 +12870,7 @@
     method public void addHotplugEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
     method public android.hardware.hdmi.HdmiPlaybackClient getPlaybackClient();
     method public android.hardware.hdmi.HdmiTvClient getTvClient();
-    method public void removeHotplugeEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
+    method public void removeHotplugEventListener(android.hardware.hdmi.HdmiControlManager.HotplugEventListener);
   }
 
   public static abstract interface HdmiControlManager.HotplugEventListener {
@@ -12868,7 +12878,6 @@
   }
 
   public final class HdmiHotplugEvent implements android.os.Parcelable {
-    ctor public HdmiHotplugEvent(int, boolean);
     method public int describeContents();
     method public int getPort();
     method public boolean isConnected();
@@ -15754,7 +15763,7 @@
     method public void setActive(boolean);
     method public void setFlags(int);
     method public void setLaunchPendingIntent(android.app.PendingIntent);
-    method public void useLocalPlayback(android.media.AudioAttributes);
+    method public void useLocalPlayback(int);
     method public void useRemotePlayback(android.media.session.RemoteVolumeProvider);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
@@ -19843,6 +19852,532 @@
     field public static final int GL_WAIT_FAILED = 37149; // 0x911d
   }
 
+  public class GLES31 extends android.opengl.GLES30 {
+    method public static void glActiveShaderProgram(int, int);
+    method public static void glBindImageTexture(int, int, int, boolean, int, int, int);
+    method public static void glBindProgramPipeline(int);
+    method public static void glBindVertexBuffer(int, int, long, int);
+    method public static int glCreateShaderProgramv(int, java.lang.String[]);
+    method public static void glDeleteProgramPipelines(int, int[], int);
+    method public static void glDeleteProgramPipelines(int, java.nio.IntBuffer);
+    method public static void glDispatchCompute(int, int, int);
+    method public static void glDispatchComputeIndirect(long);
+    method public static void glDrawArraysIndirect(int, long);
+    method public static void glDrawElementsIndirect(int, int, long);
+    method public static void glFramebufferParameteri(int, int, int);
+    method public static void glGenProgramPipelines(int, int[], int);
+    method public static void glGenProgramPipelines(int, java.nio.IntBuffer);
+    method public static void glGetBooleani_v(int, int, boolean[], int);
+    method public static void glGetBooleani_v(int, int, java.nio.IntBuffer);
+    method public static void glGetFramebufferParameteriv(int, int, int[], int);
+    method public static void glGetFramebufferParameteriv(int, int, java.nio.IntBuffer);
+    method public static void glGetMultisamplefv(int, int, float[], int);
+    method public static void glGetMultisamplefv(int, int, java.nio.FloatBuffer);
+    method public static void glGetProgramInterfaceiv(int, int, int, int[], int);
+    method public static void glGetProgramInterfaceiv(int, int, int, java.nio.IntBuffer);
+    method public static java.lang.String glGetProgramPipelineInfoLog(int);
+    method public static void glGetProgramPipelineiv(int, int, int[], int);
+    method public static void glGetProgramPipelineiv(int, int, java.nio.IntBuffer);
+    method public static int glGetProgramResourceIndex(int, int, java.lang.String);
+    method public static int glGetProgramResourceLocation(int, int, java.lang.String);
+    method public static java.lang.String glGetProgramResourceName(int, int, int);
+    method public static void glGetProgramResourceiv(int, int, int, int, int[], int, int, int[], int, int[], int);
+    method public static void glGetProgramResourceiv(int, int, int, int, java.nio.IntBuffer, int, java.nio.IntBuffer, java.nio.IntBuffer);
+    method public static void glGetTexLevelParameterfv(int, int, int, float[], int);
+    method public static void glGetTexLevelParameterfv(int, int, int, java.nio.FloatBuffer);
+    method public static void glGetTexLevelParameteriv(int, int, int, int[], int);
+    method public static void glGetTexLevelParameteriv(int, int, int, java.nio.IntBuffer);
+    method public static boolean glIsProgramPipeline(int);
+    method public static void glMemoryBarrier(int);
+    method public static void glMemoryBarrierByRegion(int);
+    method public static void glProgramUniform1f(int, int, float);
+    method public static void glProgramUniform1fv(int, int, int, float[], int);
+    method public static void glProgramUniform1fv(int, int, int, java.nio.FloatBuffer);
+    method public static void glProgramUniform1i(int, int, int);
+    method public static void glProgramUniform1iv(int, int, int, int[], int);
+    method public static void glProgramUniform1iv(int, int, int, java.nio.IntBuffer);
+    method public static void glProgramUniform1ui(int, int, int);
+    method public static void glProgramUniform1uiv(int, int, int, int[], int);
+    method public static void glProgramUniform1uiv(int, int, int, java.nio.IntBuffer);
+    method public static void glProgramUniform2f(int, int, float, float);
+    method public static void glProgramUniform2fv(int, int, int, float[], int);
+    method public static void glProgramUniform2fv(int, int, int, java.nio.FloatBuffer);
+    method public static void glProgramUniform2i(int, int, int, int);
+    method public static void glProgramUniform2iv(int, int, int, int[], int);
+    method public static void glProgramUniform2iv(int, int, int, java.nio.IntBuffer);
+    method public static void glProgramUniform2ui(int, int, int, int);
+    method public static void glProgramUniform2uiv(int, int, int, int[], int);
+    method public static void glProgramUniform2uiv(int, int, int, java.nio.IntBuffer);
+    method public static void glProgramUniform3f(int, int, float, float, float);
+    method public static void glProgramUniform3fv(int, int, int, float[], int);
+    method public static void glProgramUniform3fv(int, int, int, java.nio.FloatBuffer);
+    method public static void glProgramUniform3i(int, int, int, int, int);
+    method public static void glProgramUniform3iv(int, int, int, int[], int);
+    method public static void glProgramUniform3iv(int, int, int, java.nio.IntBuffer);
+    method public static void glProgramUniform3ui(int, int, int, int, int);
+    method public static void glProgramUniform3uiv(int, int, int, int[], int);
+    method public static void glProgramUniform3uiv(int, int, int, java.nio.IntBuffer);
+    method public static void glProgramUniform4f(int, int, float, float, float, float);
+    method public static void glProgramUniform4fv(int, int, int, float[], int);
+    method public static void glProgramUniform4fv(int, int, int, java.nio.FloatBuffer);
+    method public static void glProgramUniform4i(int, int, int, int, int, int);
+    method public static void glProgramUniform4iv(int, int, int, int[], int);
+    method public static void glProgramUniform4iv(int, int, int, java.nio.IntBuffer);
+    method public static void glProgramUniform4ui(int, int, int, int, int, int);
+    method public static void glProgramUniform4uiv(int, int, int, int[], int);
+    method public static void glProgramUniform4uiv(int, int, int, java.nio.IntBuffer);
+    method public static void glProgramUniformMatrix2fv(int, int, int, boolean, float[], int);
+    method public static void glProgramUniformMatrix2fv(int, int, int, boolean, java.nio.FloatBuffer);
+    method public static void glProgramUniformMatrix2x3fv(int, int, int, boolean, float[], int);
+    method public static void glProgramUniformMatrix2x3fv(int, int, int, boolean, java.nio.FloatBuffer);
+    method public static void glProgramUniformMatrix2x4fv(int, int, int, boolean, float[], int);
+    method public static void glProgramUniformMatrix2x4fv(int, int, int, boolean, java.nio.FloatBuffer);
+    method public static void glProgramUniformMatrix3fv(int, int, int, boolean, float[], int);
+    method public static void glProgramUniformMatrix3fv(int, int, int, boolean, java.nio.FloatBuffer);
+    method public static void glProgramUniformMatrix3x2fv(int, int, int, boolean, float[], int);
+    method public static void glProgramUniformMatrix3x2fv(int, int, int, boolean, java.nio.FloatBuffer);
+    method public static void glProgramUniformMatrix3x4fv(int, int, int, boolean, float[], int);
+    method public static void glProgramUniformMatrix3x4fv(int, int, int, boolean, java.nio.FloatBuffer);
+    method public static void glProgramUniformMatrix4fv(int, int, int, boolean, float[], int);
+    method public static void glProgramUniformMatrix4fv(int, int, int, boolean, java.nio.FloatBuffer);
+    method public static void glProgramUniformMatrix4x2fv(int, int, int, boolean, float[], int);
+    method public static void glProgramUniformMatrix4x2fv(int, int, int, boolean, java.nio.FloatBuffer);
+    method public static void glProgramUniformMatrix4x3fv(int, int, int, boolean, float[], int);
+    method public static void glProgramUniformMatrix4x3fv(int, int, int, boolean, java.nio.FloatBuffer);
+    method public static void glSampleMaski(int, int);
+    method public static void glTexStorage2DMultisample(int, int, int, int, int, boolean);
+    method public static void glUseProgramStages(int, int, int);
+    method public static void glValidateProgramPipeline(int);
+    method public static void glVertexAttribBinding(int, int);
+    method public static void glVertexAttribFormat(int, int, int, boolean, int);
+    method public static void glVertexAttribIFormat(int, int, int, int);
+    method public static void glVertexBindingDivisor(int, int);
+    field public static final int GL_ACTIVE_ATOMIC_COUNTER_BUFFERS = 37593; // 0x92d9
+    field public static final int GL_ACTIVE_PROGRAM = 33369; // 0x8259
+    field public static final int GL_ACTIVE_RESOURCES = 37621; // 0x92f5
+    field public static final int GL_ACTIVE_VARIABLES = 37637; // 0x9305
+    field public static final int GL_ALL_SHADER_BITS = -1; // 0xffffffff
+    field public static final int GL_ARRAY_SIZE = 37627; // 0x92fb
+    field public static final int GL_ARRAY_STRIDE = 37630; // 0x92fe
+    field public static final int GL_ATOMIC_COUNTER_BARRIER_BIT = 4096; // 0x1000
+    field public static final int GL_ATOMIC_COUNTER_BUFFER = 37568; // 0x92c0
+    field public static final int GL_ATOMIC_COUNTER_BUFFER_BINDING = 37569; // 0x92c1
+    field public static final int GL_ATOMIC_COUNTER_BUFFER_INDEX = 37633; // 0x9301
+    field public static final int GL_ATOMIC_COUNTER_BUFFER_SIZE = 37571; // 0x92c3
+    field public static final int GL_ATOMIC_COUNTER_BUFFER_START = 37570; // 0x92c2
+    field public static final int GL_BLOCK_INDEX = 37629; // 0x92fd
+    field public static final int GL_BUFFER_BINDING = 37634; // 0x9302
+    field public static final int GL_BUFFER_DATA_SIZE = 37635; // 0x9303
+    field public static final int GL_BUFFER_UPDATE_BARRIER_BIT = 512; // 0x200
+    field public static final int GL_BUFFER_VARIABLE = 37605; // 0x92e5
+    field public static final int GL_COMMAND_BARRIER_BIT = 64; // 0x40
+    field public static final int GL_COMPUTE_SHADER = 37305; // 0x91b9
+    field public static final int GL_COMPUTE_SHADER_BIT = 32; // 0x20
+    field public static final int GL_COMPUTE_WORK_GROUP_SIZE = 33383; // 0x8267
+    field public static final int GL_DEPTH_STENCIL_TEXTURE_MODE = 37098; // 0x90ea
+    field public static final int GL_DISPATCH_INDIRECT_BUFFER = 37102; // 0x90ee
+    field public static final int GL_DISPATCH_INDIRECT_BUFFER_BINDING = 37103; // 0x90ef
+    field public static final int GL_DRAW_INDIRECT_BUFFER = 36671; // 0x8f3f
+    field public static final int GL_DRAW_INDIRECT_BUFFER_BINDING = 36675; // 0x8f43
+    field public static final int GL_FRAGMENT_SHADER_BIT = 2; // 0x2
+    field public static final int GL_FRAMEBUFFER_BARRIER_BIT = 1024; // 0x400
+    field public static final int GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS = 37652; // 0x9314
+    field public static final int GL_FRAMEBUFFER_DEFAULT_HEIGHT = 37649; // 0x9311
+    field public static final int GL_FRAMEBUFFER_DEFAULT_SAMPLES = 37651; // 0x9313
+    field public static final int GL_FRAMEBUFFER_DEFAULT_WIDTH = 37648; // 0x9310
+    field public static final int GL_IMAGE_2D = 36941; // 0x904d
+    field public static final int GL_IMAGE_2D_ARRAY = 36947; // 0x9053
+    field public static final int GL_IMAGE_3D = 36942; // 0x904e
+    field public static final int GL_IMAGE_BINDING_ACCESS = 36670; // 0x8f3e
+    field public static final int GL_IMAGE_BINDING_FORMAT = 36974; // 0x906e
+    field public static final int GL_IMAGE_BINDING_LAYER = 36669; // 0x8f3d
+    field public static final int GL_IMAGE_BINDING_LAYERED = 36668; // 0x8f3c
+    field public static final int GL_IMAGE_BINDING_LEVEL = 36667; // 0x8f3b
+    field public static final int GL_IMAGE_BINDING_NAME = 36666; // 0x8f3a
+    field public static final int GL_IMAGE_CUBE = 36944; // 0x9050
+    field public static final int GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS = 37065; // 0x90c9
+    field public static final int GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE = 37064; // 0x90c8
+    field public static final int GL_IMAGE_FORMAT_COMPATIBILITY_TYPE = 37063; // 0x90c7
+    field public static final int GL_INT_IMAGE_2D = 36952; // 0x9058
+    field public static final int GL_INT_IMAGE_2D_ARRAY = 36958; // 0x905e
+    field public static final int GL_INT_IMAGE_3D = 36953; // 0x9059
+    field public static final int GL_INT_IMAGE_CUBE = 36955; // 0x905b
+    field public static final int GL_INT_SAMPLER_2D_MULTISAMPLE = 37129; // 0x9109
+    field public static final int GL_IS_ROW_MAJOR = 37632; // 0x9300
+    field public static final int GL_LOCATION = 37646; // 0x930e
+    field public static final int GL_MATRIX_STRIDE = 37631; // 0x92ff
+    field public static final int GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS = 37596; // 0x92dc
+    field public static final int GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE = 37592; // 0x92d8
+    field public static final int GL_MAX_COLOR_TEXTURE_SAMPLES = 37134; // 0x910e
+    field public static final int GL_MAX_COMBINED_ATOMIC_COUNTERS = 37591; // 0x92d7
+    field public static final int GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS = 37585; // 0x92d1
+    field public static final int GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS = 33382; // 0x8266
+    field public static final int GL_MAX_COMBINED_IMAGE_UNIFORMS = 37071; // 0x90cf
+    field public static final int GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES = 36665; // 0x8f39
+    field public static final int GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS = 37084; // 0x90dc
+    field public static final int GL_MAX_COMPUTE_ATOMIC_COUNTERS = 33381; // 0x8265
+    field public static final int GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS = 33380; // 0x8264
+    field public static final int GL_MAX_COMPUTE_IMAGE_UNIFORMS = 37309; // 0x91bd
+    field public static final int GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS = 37083; // 0x90db
+    field public static final int GL_MAX_COMPUTE_SHARED_MEMORY_SIZE = 33378; // 0x8262
+    field public static final int GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS = 37308; // 0x91bc
+    field public static final int GL_MAX_COMPUTE_UNIFORM_BLOCKS = 37307; // 0x91bb
+    field public static final int GL_MAX_COMPUTE_UNIFORM_COMPONENTS = 33379; // 0x8263
+    field public static final int GL_MAX_COMPUTE_WORK_GROUP_COUNT = 37310; // 0x91be
+    field public static final int GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS = 37099; // 0x90eb
+    field public static final int GL_MAX_COMPUTE_WORK_GROUP_SIZE = 37311; // 0x91bf
+    field public static final int GL_MAX_DEPTH_TEXTURE_SAMPLES = 37135; // 0x910f
+    field public static final int GL_MAX_FRAGMENT_ATOMIC_COUNTERS = 37590; // 0x92d6
+    field public static final int GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS = 37584; // 0x92d0
+    field public static final int GL_MAX_FRAGMENT_IMAGE_UNIFORMS = 37070; // 0x90ce
+    field public static final int GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS = 37082; // 0x90da
+    field public static final int GL_MAX_FRAMEBUFFER_HEIGHT = 37654; // 0x9316
+    field public static final int GL_MAX_FRAMEBUFFER_SAMPLES = 37656; // 0x9318
+    field public static final int GL_MAX_FRAMEBUFFER_WIDTH = 37653; // 0x9315
+    field public static final int GL_MAX_IMAGE_UNITS = 36664; // 0x8f38
+    field public static final int GL_MAX_INTEGER_SAMPLES = 37136; // 0x9110
+    field public static final int GL_MAX_NAME_LENGTH = 37622; // 0x92f6
+    field public static final int GL_MAX_NUM_ACTIVE_VARIABLES = 37623; // 0x92f7
+    field public static final int GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET = 36447; // 0x8e5f
+    field public static final int GL_MAX_SAMPLE_MASK_WORDS = 36441; // 0x8e59
+    field public static final int GL_MAX_SHADER_STORAGE_BLOCK_SIZE = 37086; // 0x90de
+    field public static final int GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS = 37085; // 0x90dd
+    field public static final int GL_MAX_UNIFORM_LOCATIONS = 33390; // 0x826e
+    field public static final int GL_MAX_VERTEX_ATOMIC_COUNTERS = 37586; // 0x92d2
+    field public static final int GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS = 37580; // 0x92cc
+    field public static final int GL_MAX_VERTEX_ATTRIB_BINDINGS = 33498; // 0x82da
+    field public static final int GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET = 33497; // 0x82d9
+    field public static final int GL_MAX_VERTEX_ATTRIB_STRIDE = 33509; // 0x82e5
+    field public static final int GL_MAX_VERTEX_IMAGE_UNIFORMS = 37066; // 0x90ca
+    field public static final int GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS = 37078; // 0x90d6
+    field public static final int GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET = 36446; // 0x8e5e
+    field public static final int GL_NAME_LENGTH = 37625; // 0x92f9
+    field public static final int GL_NUM_ACTIVE_VARIABLES = 37636; // 0x9304
+    field public static final int GL_OFFSET = 37628; // 0x92fc
+    field public static final int GL_PIXEL_BUFFER_BARRIER_BIT = 128; // 0x80
+    field public static final int GL_PROGRAM_INPUT = 37603; // 0x92e3
+    field public static final int GL_PROGRAM_OUTPUT = 37604; // 0x92e4
+    field public static final int GL_PROGRAM_PIPELINE_BINDING = 33370; // 0x825a
+    field public static final int GL_PROGRAM_SEPARABLE = 33368; // 0x8258
+    field public static final int GL_READ_ONLY = 35000; // 0x88b8
+    field public static final int GL_READ_WRITE = 35002; // 0x88ba
+    field public static final int GL_REFERENCED_BY_COMPUTE_SHADER = 37643; // 0x930b
+    field public static final int GL_REFERENCED_BY_FRAGMENT_SHADER = 37642; // 0x930a
+    field public static final int GL_REFERENCED_BY_VERTEX_SHADER = 37638; // 0x9306
+    field public static final int GL_SAMPLER_2D_MULTISAMPLE = 37128; // 0x9108
+    field public static final int GL_SAMPLE_MASK = 36433; // 0x8e51
+    field public static final int GL_SAMPLE_MASK_VALUE = 36434; // 0x8e52
+    field public static final int GL_SAMPLE_POSITION = 36432; // 0x8e50
+    field public static final int GL_SHADER_STORAGE_BARRIER_BIT = 8192; // 0x2000
+    field public static final int GL_SHADER_STORAGE_BLOCK = 37606; // 0x92e6
+    field public static final int GL_SHADER_STORAGE_BUFFER = 37074; // 0x90d2
+    field public static final int GL_SHADER_STORAGE_BUFFER_BINDING = 37075; // 0x90d3
+    field public static final int GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT = 37087; // 0x90df
+    field public static final int GL_SHADER_STORAGE_BUFFER_SIZE = 37077; // 0x90d5
+    field public static final int GL_SHADER_STORAGE_BUFFER_START = 37076; // 0x90d4
+    field public static final int GL_STENCIL_INDEX = 6401; // 0x1901
+    field public static final int GL_TEXTURE_2D_MULTISAMPLE = 37120; // 0x9100
+    field public static final int GL_TEXTURE_ALPHA_SIZE = 32863; // 0x805f
+    field public static final int GL_TEXTURE_ALPHA_TYPE = 35859; // 0x8c13
+    field public static final int GL_TEXTURE_BINDING_2D_MULTISAMPLE = 37124; // 0x9104
+    field public static final int GL_TEXTURE_BLUE_SIZE = 32862; // 0x805e
+    field public static final int GL_TEXTURE_BLUE_TYPE = 35858; // 0x8c12
+    field public static final int GL_TEXTURE_COMPRESSED = 34465; // 0x86a1
+    field public static final int GL_TEXTURE_DEPTH = 32881; // 0x8071
+    field public static final int GL_TEXTURE_DEPTH_SIZE = 34890; // 0x884a
+    field public static final int GL_TEXTURE_DEPTH_TYPE = 35862; // 0x8c16
+    field public static final int GL_TEXTURE_FETCH_BARRIER_BIT = 8; // 0x8
+    field public static final int GL_TEXTURE_FIXED_SAMPLE_LOCATIONS = 37127; // 0x9107
+    field public static final int GL_TEXTURE_GREEN_SIZE = 32861; // 0x805d
+    field public static final int GL_TEXTURE_GREEN_TYPE = 35857; // 0x8c11
+    field public static final int GL_TEXTURE_HEIGHT = 4097; // 0x1001
+    field public static final int GL_TEXTURE_INTERNAL_FORMAT = 4099; // 0x1003
+    field public static final int GL_TEXTURE_RED_SIZE = 32860; // 0x805c
+    field public static final int GL_TEXTURE_RED_TYPE = 35856; // 0x8c10
+    field public static final int GL_TEXTURE_SAMPLES = 37126; // 0x9106
+    field public static final int GL_TEXTURE_SHARED_SIZE = 35903; // 0x8c3f
+    field public static final int GL_TEXTURE_STENCIL_SIZE = 35057; // 0x88f1
+    field public static final int GL_TEXTURE_UPDATE_BARRIER_BIT = 256; // 0x100
+    field public static final int GL_TEXTURE_WIDTH = 4096; // 0x1000
+    field public static final int GL_TOP_LEVEL_ARRAY_SIZE = 37644; // 0x930c
+    field public static final int GL_TOP_LEVEL_ARRAY_STRIDE = 37645; // 0x930d
+    field public static final int GL_TRANSFORM_FEEDBACK_BARRIER_BIT = 2048; // 0x800
+    field public static final int GL_TRANSFORM_FEEDBACK_VARYING = 37620; // 0x92f4
+    field public static final int GL_TYPE = 37626; // 0x92fa
+    field public static final int GL_UNIFORM = 37601; // 0x92e1
+    field public static final int GL_UNIFORM_BARRIER_BIT = 4; // 0x4
+    field public static final int GL_UNIFORM_BLOCK = 37602; // 0x92e2
+    field public static final int GL_UNSIGNED_INT_ATOMIC_COUNTER = 37595; // 0x92db
+    field public static final int GL_UNSIGNED_INT_IMAGE_2D = 36963; // 0x9063
+    field public static final int GL_UNSIGNED_INT_IMAGE_2D_ARRAY = 36969; // 0x9069
+    field public static final int GL_UNSIGNED_INT_IMAGE_3D = 36964; // 0x9064
+    field public static final int GL_UNSIGNED_INT_IMAGE_CUBE = 36966; // 0x9066
+    field public static final int GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE = 37130; // 0x910a
+    field public static final int GL_VERTEX_ATTRIB_BINDING = 33492; // 0x82d4
+    field public static final int GL_VERTEX_ATTRIB_RELATIVE_OFFSET = 33493; // 0x82d5
+    field public static final int GL_VERTEX_BINDING_BUFFER = 36687; // 0x8f4f
+    field public static final int GL_VERTEX_BINDING_DIVISOR = 33494; // 0x82d6
+    field public static final int GL_VERTEX_BINDING_OFFSET = 33495; // 0x82d7
+    field public static final int GL_VERTEX_BINDING_STRIDE = 33496; // 0x82d8
+    field public static final int GL_VERTEX_SHADER_BIT = 1; // 0x1
+    field public static final int GL_WRITE_ONLY = 35001; // 0x88b9
+  }
+
+  public class GLES31Ext {
+    method public static void glBlendBarrierKHR();
+    method public static void glBlendEquationSeparateiEXT(int, int, int);
+    method public static void glBlendEquationiEXT(int, int);
+    method public static void glBlendFuncSeparateiEXT(int, int, int, int, int);
+    method public static void glBlendFunciEXT(int, int, int);
+    method public static void glColorMaskiEXT(int, boolean, boolean, boolean, boolean);
+    method public static void glCopyImageSubDataEXT(int, int, int, int, int, int, int, int, int, int, int, int, int, int, int);
+    method public static void glDebugMessageCallbackKHR(android.opengl.GLES31Ext.DebugProcKHR);
+    method public static void glDebugMessageControlKHR(int, int, int, int, int[], int, boolean);
+    method public static void glDebugMessageControlKHR(int, int, int, int, java.nio.IntBuffer, boolean);
+    method public static void glDebugMessageInsertKHR(int, int, int, int, java.lang.String);
+    method public static void glDisableiEXT(int, int);
+    method public static void glEnableiEXT(int, int);
+    method public static void glFramebufferTextureEXT(int, int, int, int);
+    method public static android.opengl.GLES31Ext.DebugProcKHR glGetDebugMessageCallbackKHR();
+    method public static int glGetDebugMessageLogKHR(int, int, int[], int, int[], int, int[], int, int[], int, int[], int, byte[], int);
+    method public static int glGetDebugMessageLogKHR(int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.ByteBuffer);
+    method public static java.lang.String[] glGetDebugMessageLogKHR(int, int[], int, int[], int, int[], int, int[], int);
+    method public static java.lang.String[] glGetDebugMessageLogKHR(int, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer, java.nio.IntBuffer);
+    method public static java.lang.String glGetObjectLabelKHR(int, int);
+    method public static java.lang.String glGetObjectPtrLabelKHR(long);
+    method public static void glGetSamplerParameterIivEXT(int, int, int[], int);
+    method public static void glGetSamplerParameterIivEXT(int, int, java.nio.IntBuffer);
+    method public static void glGetSamplerParameterIuivEXT(int, int, int[], int);
+    method public static void glGetSamplerParameterIuivEXT(int, int, java.nio.IntBuffer);
+    method public static void glGetTexParameterIivEXT(int, int, int[], int);
+    method public static void glGetTexParameterIivEXT(int, int, java.nio.IntBuffer);
+    method public static void glGetTexParameterIuivEXT(int, int, int[], int);
+    method public static void glGetTexParameterIuivEXT(int, int, java.nio.IntBuffer);
+    method public static boolean glIsEnablediEXT(int, int);
+    method public static void glMinSampleShadingOES(float);
+    method public static void glObjectLabelKHR(int, int, int, java.lang.String);
+    method public static void glObjectPtrLabelKHR(long, java.lang.String);
+    method public static void glPatchParameteriEXT(int, int);
+    method public static void glPopDebugGroupKHR();
+    method public static void glPrimitiveBoundingBoxEXT(float, float, float, float, float, float, float, float);
+    method public static void glPushDebugGroupKHR(int, int, int, java.lang.String);
+    method public static void glSamplerParameterIivEXT(int, int, int[], int);
+    method public static void glSamplerParameterIivEXT(int, int, java.nio.IntBuffer);
+    method public static void glSamplerParameterIuivEXT(int, int, int[], int);
+    method public static void glSamplerParameterIuivEXT(int, int, java.nio.IntBuffer);
+    method public static void glTexBufferEXT(int, int, int);
+    method public static void glTexBufferRangeEXT(int, int, int, int, int);
+    method public static void glTexParameterIivEXT(int, int, int[], int);
+    method public static void glTexParameterIivEXT(int, int, java.nio.IntBuffer);
+    method public static void glTexParameterIuivEXT(int, int, int[], int);
+    method public static void glTexParameterIuivEXT(int, int, java.nio.IntBuffer);
+    method public static void glTexStorage3DMultisampleOES(int, int, int, int, int, int, boolean);
+    field public static final int GL_BLEND_ADVANCED_COHERENT_KHR = 37509; // 0x9285
+    field public static final int GL_BUFFER_KHR = 33504; // 0x82e0
+    field public static final int GL_CLAMP_TO_BORDER_EXT = 33069; // 0x812d
+    field public static final int GL_COLORBURN_KHR = 37530; // 0x929a
+    field public static final int GL_COLORDODGE_KHR = 37529; // 0x9299
+    field public static final int GL_COMPRESSED_RGBA_ASTC_10x10_KHR = 37819; // 0x93bb
+    field public static final int GL_COMPRESSED_RGBA_ASTC_10x5_KHR = 37816; // 0x93b8
+    field public static final int GL_COMPRESSED_RGBA_ASTC_10x6_KHR = 37817; // 0x93b9
+    field public static final int GL_COMPRESSED_RGBA_ASTC_10x8_KHR = 37818; // 0x93ba
+    field public static final int GL_COMPRESSED_RGBA_ASTC_12x10_KHR = 37820; // 0x93bc
+    field public static final int GL_COMPRESSED_RGBA_ASTC_12x12_KHR = 37821; // 0x93bd
+    field public static final int GL_COMPRESSED_RGBA_ASTC_4x4_KHR = 37808; // 0x93b0
+    field public static final int GL_COMPRESSED_RGBA_ASTC_5x4_KHR = 37809; // 0x93b1
+    field public static final int GL_COMPRESSED_RGBA_ASTC_5x5_KHR = 37810; // 0x93b2
+    field public static final int GL_COMPRESSED_RGBA_ASTC_6x5_KHR = 37811; // 0x93b3
+    field public static final int GL_COMPRESSED_RGBA_ASTC_6x6_KHR = 37812; // 0x93b4
+    field public static final int GL_COMPRESSED_RGBA_ASTC_8x5_KHR = 37813; // 0x93b5
+    field public static final int GL_COMPRESSED_RGBA_ASTC_8x6_KHR = 37814; // 0x93b6
+    field public static final int GL_COMPRESSED_RGBA_ASTC_8x8_KHR = 37815; // 0x93b7
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR = 37851; // 0x93db
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR = 37848; // 0x93d8
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR = 37849; // 0x93d9
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR = 37850; // 0x93da
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR = 37852; // 0x93dc
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR = 37853; // 0x93dd
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR = 37840; // 0x93d0
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR = 37841; // 0x93d1
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR = 37842; // 0x93d2
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR = 37843; // 0x93d3
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR = 37844; // 0x93d4
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR = 37845; // 0x93d5
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR = 37846; // 0x93d6
+    field public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR = 37847; // 0x93d7
+    field public static final int GL_CONTEXT_FLAG_DEBUG_BIT_KHR = 2; // 0x2
+    field public static final int GL_DARKEN_KHR = 37527; // 0x9297
+    field public static final int GL_DEBUG_CALLBACK_FUNCTION_KHR = 33348; // 0x8244
+    field public static final int GL_DEBUG_CALLBACK_USER_PARAM_KHR = 33349; // 0x8245
+    field public static final int GL_DEBUG_GROUP_STACK_DEPTH_KHR = 33389; // 0x826d
+    field public static final int GL_DEBUG_LOGGED_MESSAGES_KHR = 37189; // 0x9145
+    field public static final int GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR = 33347; // 0x8243
+    field public static final int GL_DEBUG_OUTPUT_KHR = 37600; // 0x92e0
+    field public static final int GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR = 33346; // 0x8242
+    field public static final int GL_DEBUG_SEVERITY_HIGH_KHR = 37190; // 0x9146
+    field public static final int GL_DEBUG_SEVERITY_LOW_KHR = 37192; // 0x9148
+    field public static final int GL_DEBUG_SEVERITY_MEDIUM_KHR = 37191; // 0x9147
+    field public static final int GL_DEBUG_SEVERITY_NOTIFICATION_KHR = 33387; // 0x826b
+    field public static final int GL_DEBUG_SOURCE_API_KHR = 33350; // 0x8246
+    field public static final int GL_DEBUG_SOURCE_APPLICATION_KHR = 33354; // 0x824a
+    field public static final int GL_DEBUG_SOURCE_OTHER_KHR = 33355; // 0x824b
+    field public static final int GL_DEBUG_SOURCE_SHADER_COMPILER_KHR = 33352; // 0x8248
+    field public static final int GL_DEBUG_SOURCE_THIRD_PARTY_KHR = 33353; // 0x8249
+    field public static final int GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR = 33351; // 0x8247
+    field public static final int GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR = 33357; // 0x824d
+    field public static final int GL_DEBUG_TYPE_ERROR_KHR = 33356; // 0x824c
+    field public static final int GL_DEBUG_TYPE_MARKER_KHR = 33384; // 0x8268
+    field public static final int GL_DEBUG_TYPE_OTHER_KHR = 33361; // 0x8251
+    field public static final int GL_DEBUG_TYPE_PERFORMANCE_KHR = 33360; // 0x8250
+    field public static final int GL_DEBUG_TYPE_POP_GROUP_KHR = 33386; // 0x826a
+    field public static final int GL_DEBUG_TYPE_PORTABILITY_KHR = 33359; // 0x824f
+    field public static final int GL_DEBUG_TYPE_PUSH_GROUP_KHR = 33385; // 0x8269
+    field public static final int GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR = 33358; // 0x824e
+    field public static final int GL_DECODE_EXT = 35401; // 0x8a49
+    field public static final int GL_DIFFERENCE_KHR = 37534; // 0x929e
+    field public static final int GL_EXCLUSION_KHR = 37536; // 0x92a0
+    field public static final int GL_FIRST_VERTEX_CONVENTION_EXT = 36429; // 0x8e4d
+    field public static final int GL_FRACTIONAL_EVEN_EXT = 36476; // 0x8e7c
+    field public static final int GL_FRACTIONAL_ODD_EXT = 36475; // 0x8e7b
+    field public static final int GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES = 36445; // 0x8e5d
+    field public static final int GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT = 36263; // 0x8da7
+    field public static final int GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT = 37650; // 0x9312
+    field public static final int GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT = 36264; // 0x8da8
+    field public static final int GL_GEOMETRY_LINKED_INPUT_TYPE_EXT = 35095; // 0x8917
+    field public static final int GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT = 35096; // 0x8918
+    field public static final int GL_GEOMETRY_LINKED_VERTICES_OUT_EXT = 35094; // 0x8916
+    field public static final int GL_GEOMETRY_SHADER_BIT_EXT = 4; // 0x4
+    field public static final int GL_GEOMETRY_SHADER_EXT = 36313; // 0x8dd9
+    field public static final int GL_GEOMETRY_SHADER_INVOCATIONS_EXT = 34943; // 0x887f
+    field public static final int GL_HARDLIGHT_KHR = 37531; // 0x929b
+    field public static final int GL_HSL_COLOR_KHR = 37551; // 0x92af
+    field public static final int GL_HSL_HUE_KHR = 37549; // 0x92ad
+    field public static final int GL_HSL_LUMINOSITY_KHR = 37552; // 0x92b0
+    field public static final int GL_HSL_SATURATION_KHR = 37550; // 0x92ae
+    field public static final int GL_IMAGE_BUFFER_EXT = 36945; // 0x9051
+    field public static final int GL_IMAGE_CUBE_MAP_ARRAY_EXT = 36948; // 0x9054
+    field public static final int GL_INT_IMAGE_BUFFER_EXT = 36956; // 0x905c
+    field public static final int GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT = 36959; // 0x905f
+    field public static final int GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES = 37132; // 0x910c
+    field public static final int GL_INT_SAMPLER_BUFFER_EXT = 36304; // 0x8dd0
+    field public static final int GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT = 36878; // 0x900e
+    field public static final int GL_ISOLINES_EXT = 36474; // 0x8e7a
+    field public static final int GL_IS_PER_PATCH_EXT = 37607; // 0x92e7
+    field public static final int GL_LAST_VERTEX_CONVENTION_EXT = 36430; // 0x8e4e
+    field public static final int GL_LAYER_PROVOKING_VERTEX_EXT = 33374; // 0x825e
+    field public static final int GL_LIGHTEN_KHR = 37528; // 0x9298
+    field public static final int GL_LINES_ADJACENCY_EXT = 10; // 0xa
+    field public static final int GL_LINE_STRIP_ADJACENCY_EXT = 11; // 0xb
+    field public static final int GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT = 35378; // 0x8a32
+    field public static final int GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT = 36382; // 0x8e1e
+    field public static final int GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT = 36383; // 0x8e1f
+    field public static final int GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR = 33388; // 0x826c
+    field public static final int GL_MAX_DEBUG_LOGGED_MESSAGES_KHR = 37188; // 0x9144
+    field public static final int GL_MAX_DEBUG_MESSAGE_LENGTH_KHR = 37187; // 0x9143
+    field public static final int GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES = 36444; // 0x8e5c
+    field public static final int GL_MAX_FRAMEBUFFER_LAYERS_EXT = 37655; // 0x9317
+    field public static final int GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT = 37589; // 0x92d5
+    field public static final int GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT = 37583; // 0x92cf
+    field public static final int GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT = 37069; // 0x90cd
+    field public static final int GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT = 37155; // 0x9123
+    field public static final int GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT = 37156; // 0x9124
+    field public static final int GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT = 36320; // 0x8de0
+    field public static final int GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT = 36442; // 0x8e5a
+    field public static final int GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT = 37079; // 0x90d7
+    field public static final int GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT = 35881; // 0x8c29
+    field public static final int GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT = 36321; // 0x8de1
+    field public static final int GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT = 35372; // 0x8a2c
+    field public static final int GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT = 36319; // 0x8ddf
+    field public static final int GL_MAX_LABEL_LENGTH_KHR = 33512; // 0x82e8
+    field public static final int GL_MAX_PATCH_VERTICES_EXT = 36477; // 0x8e7d
+    field public static final int GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT = 37587; // 0x92d3
+    field public static final int GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT = 37581; // 0x92cd
+    field public static final int GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT = 37067; // 0x90cb
+    field public static final int GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT = 34924; // 0x886c
+    field public static final int GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT = 36483; // 0x8e83
+    field public static final int GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT = 37080; // 0x90d8
+    field public static final int GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT = 36481; // 0x8e81
+    field public static final int GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT = 36485; // 0x8e85
+    field public static final int GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT = 36489; // 0x8e89
+    field public static final int GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT = 36479; // 0x8e7f
+    field public static final int GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT = 37588; // 0x92d4
+    field public static final int GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT = 37582; // 0x92ce
+    field public static final int GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT = 37068; // 0x90cc
+    field public static final int GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT = 34925; // 0x886d
+    field public static final int GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT = 36486; // 0x8e86
+    field public static final int GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT = 37081; // 0x90d9
+    field public static final int GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT = 36482; // 0x8e82
+    field public static final int GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT = 36490; // 0x8e8a
+    field public static final int GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT = 36480; // 0x8e80
+    field public static final int GL_MAX_TESS_GEN_LEVEL_EXT = 36478; // 0x8e7e
+    field public static final int GL_MAX_TESS_PATCH_COMPONENTS_EXT = 36484; // 0x8e84
+    field public static final int GL_MAX_TEXTURE_BUFFER_SIZE_EXT = 35883; // 0x8c2b
+    field public static final int GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES = 36443; // 0x8e5b
+    field public static final int GL_MIN_SAMPLE_SHADING_VALUE_OES = 35895; // 0x8c37
+    field public static final int GL_MULTIPLY_KHR = 37524; // 0x9294
+    field public static final int GL_OVERLAY_KHR = 37526; // 0x9296
+    field public static final int GL_PATCHES_EXT = 14; // 0xe
+    field public static final int GL_PATCH_VERTICES_EXT = 36466; // 0x8e72
+    field public static final int GL_PRIMITIVES_GENERATED_EXT = 35975; // 0x8c87
+    field public static final int GL_PRIMITIVE_BOUNDING_BOX_EXT = 37566; // 0x92be
+    field public static final int GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED = 33313; // 0x8221
+    field public static final int GL_PROGRAM_KHR = 33506; // 0x82e2
+    field public static final int GL_QUADS_EXT = 7; // 0x7
+    field public static final int GL_QUERY_KHR = 33507; // 0x82e3
+    field public static final int GL_REFERENCED_BY_GEOMETRY_SHADER_EXT = 37641; // 0x9309
+    field public static final int GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT = 37639; // 0x9307
+    field public static final int GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT = 37640; // 0x9308
+    field public static final int GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES = 37131; // 0x910b
+    field public static final int GL_SAMPLER_BUFFER_EXT = 36290; // 0x8dc2
+    field public static final int GL_SAMPLER_CUBE_MAP_ARRAY_EXT = 36876; // 0x900c
+    field public static final int GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT = 36877; // 0x900d
+    field public static final int GL_SAMPLER_KHR = 33510; // 0x82e6
+    field public static final int GL_SAMPLE_SHADING_OES = 35894; // 0x8c36
+    field public static final int GL_SCREEN_KHR = 37525; // 0x9295
+    field public static final int GL_SHADER_KHR = 33505; // 0x82e1
+    field public static final int GL_SKIP_DECODE_EXT = 35402; // 0x8a4a
+    field public static final int GL_SOFTLIGHT_KHR = 37532; // 0x929c
+    field public static final int GL_STACK_OVERFLOW_KHR = 1283; // 0x503
+    field public static final int GL_STACK_UNDERFLOW_KHR = 1284; // 0x504
+    field public static final int GL_STENCIL_INDEX8_OES = 36168; // 0x8d48
+    field public static final int GL_STENCIL_INDEX_OES = 6401; // 0x1901
+    field public static final int GL_TESS_CONTROL_OUTPUT_VERTICES_EXT = 36469; // 0x8e75
+    field public static final int GL_TESS_CONTROL_SHADER_BIT_EXT = 8; // 0x8
+    field public static final int GL_TESS_CONTROL_SHADER_EXT = 36488; // 0x8e88
+    field public static final int GL_TESS_EVALUATION_SHADER_BIT_EXT = 16; // 0x10
+    field public static final int GL_TESS_EVALUATION_SHADER_EXT = 36487; // 0x8e87
+    field public static final int GL_TESS_GEN_MODE_EXT = 36470; // 0x8e76
+    field public static final int GL_TESS_GEN_POINT_MODE_EXT = 36473; // 0x8e79
+    field public static final int GL_TESS_GEN_SPACING_EXT = 36471; // 0x8e77
+    field public static final int GL_TESS_GEN_VERTEX_ORDER_EXT = 36472; // 0x8e78
+    field public static final int GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES = 37122; // 0x9102
+    field public static final int GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES = 37125; // 0x9105
+    field public static final int GL_TEXTURE_BINDING_BUFFER_EXT = 35884; // 0x8c2c
+    field public static final int GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT = 36874; // 0x900a
+    field public static final int GL_TEXTURE_BORDER_COLOR_EXT = 4100; // 0x1004
+    field public static final int GL_TEXTURE_BUFFER_BINDING_EXT = 35882; // 0x8c2a
+    field public static final int GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT = 35885; // 0x8c2d
+    field public static final int GL_TEXTURE_BUFFER_EXT = 35882; // 0x8c2a
+    field public static final int GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT = 37279; // 0x919f
+    field public static final int GL_TEXTURE_BUFFER_OFFSET_EXT = 37277; // 0x919d
+    field public static final int GL_TEXTURE_BUFFER_SIZE_EXT = 37278; // 0x919e
+    field public static final int GL_TEXTURE_CUBE_MAP_ARRAY_EXT = 36873; // 0x9009
+    field public static final int GL_TEXTURE_SRGB_DECODE_EXT = 35400; // 0x8a48
+    field public static final int GL_TRIANGLES_ADJACENCY_EXT = 12; // 0xc
+    field public static final int GL_TRIANGLE_STRIP_ADJACENCY_EXT = 13; // 0xd
+    field public static final int GL_UNDEFINED_VERTEX_EXT = 33376; // 0x8260
+    field public static final int GL_UNSIGNED_INT_IMAGE_BUFFER_EXT = 36967; // 0x9067
+    field public static final int GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT = 36970; // 0x906a
+    field public static final int GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES = 37133; // 0x910d
+    field public static final int GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT = 36312; // 0x8dd8
+    field public static final int GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT = 36879; // 0x900f
+    field public static final int GL_VERTEX_ARRAY_KHR = 32884; // 0x8074
+  }
+
+  public static abstract interface GLES31Ext.DebugProcKHR {
+    method public abstract void onMessage(int, int, int, int, java.lang.String);
+  }
+
   public class GLException extends java.lang.RuntimeException {
     ctor public GLException(int);
     ctor public GLException(int, java.lang.String);
@@ -20031,7 +20566,7 @@
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int CURRENT_AVERAGE = 3; // 0x3
     field public static final int CURRENT_NOW = 2; // 0x2
-    field public static final int ENERGY_COUNTER = 4; // 0x4
+    field public static final int ENERGY_COUNTER = 5; // 0x5
   }
 
   public class Binder implements android.os.IBinder {
@@ -23428,6 +23963,7 @@
     method public static java.lang.String getSearchDocumentsQuery(android.net.Uri);
     method public static java.lang.String getViaDocumentId(android.net.Uri);
     method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
+    method public static android.net.Uri renameDocument(android.content.ContentResolver, android.net.Uri, java.lang.String);
     field public static final java.lang.String EXTRA_ERROR = "error";
     field public static final java.lang.String EXTRA_INFO = "info";
     field public static final java.lang.String EXTRA_LOADING = "loading";
@@ -23447,6 +23983,7 @@
     field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 32; // 0x20
     field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8
     field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
+    field public static final int FLAG_SUPPORTS_RENAME = 64; // 0x40
     field public static final int FLAG_SUPPORTS_THUMBNAIL = 1; // 0x1
     field public static final int FLAG_SUPPORTS_WRITE = 2; // 0x2
     field public static final java.lang.String MIME_TYPE_DIR = "vnd.android.document/directory";
@@ -23491,6 +24028,7 @@
     method public android.database.Cursor queryRecentDocuments(java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor queryRoots(java.lang.String[]) throws java.io.FileNotFoundException;
     method public android.database.Cursor querySearchDocuments(java.lang.String, java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
+    method public java.lang.String renameDocument(java.lang.String, java.lang.String) throws java.io.FileNotFoundException;
     method public final void revokeDocumentPermission(java.lang.String);
     method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
   }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 9053af2..1634d11 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -73,6 +73,8 @@
 import android.media.session.MediaSessionManager;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
+import android.net.EthernetManager;
+import android.net.IEthernetManager;
 import android.net.INetworkPolicyManager;
 import android.net.NetworkPolicyManager;
 import android.net.NetworkScoreManager;
@@ -599,6 +601,13 @@
                 return new WifiScanner(ctx.getOuterContext(), service);
             }});
 
+        registerService(ETHERNET_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
+                    IBinder b = ServiceManager.getService(ETHERNET_SERVICE);
+                    IEthernetManager service = IEthernetManager.Stub.asInterface(b);
+                    return new EthernetManager(ctx.getOuterContext(), service);
+                }});
+
         registerService(WINDOW_SERVICE, new ServiceFetcher() {
                 Display mDefaultDisplay;
                 public Object getService(ContextImpl ctx) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 59b3a27..dfd927f 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -23,6 +23,7 @@
 import android.graphics.Bitmap;
 import android.graphics.PorterDuff;
 import android.media.AudioManager;
+import android.media.session.MediaSessionToken;
 import android.net.Uri;
 import android.os.BadParcelableException;
 import android.os.Build;
@@ -686,6 +687,11 @@
      * notifications, each of which was supplied to {@link InboxStyle#addLine(CharSequence)}.
      */
     public static final String EXTRA_TEXT_LINES = "android.textLines";
+
+    /**
+     * {@link #extras} key: A string representing the name of the specific
+     * {@link android.app.Notification.Style} used to create this notification.
+     */
     public static final String EXTRA_TEMPLATE = "android.template";
 
     /**
@@ -715,6 +721,24 @@
     public static final String EXTRA_ALLOW_DURING_SETUP = "android.allowDuringSetup";
 
     /**
+     * {@link #extras} key: A
+     * {@link android.content.ContentUris content URI} pointing to an image that can be displayed
+     * in the background when the notification is selected. The URI must point to an image stream
+     * suitable for passing into
+     * {@link android.graphics.BitmapFactory#decodeStream(java.io.InputStream)
+     * BitmapFactory.decodeStream}; all other content types will be ignored. The content provider
+     * URI used for this purpose must require no permissions to read the image data.
+     */
+    public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri";
+
+    /**
+     * {@link #extras} key: A
+     * {@link android.media.session.MediaSessionToken} associated with a
+     * {@link android.app.Notification.MediaStyle} notification.
+     */
+    public static final String EXTRA_MEDIA_SESSION = "android.mediaSession";
+
+    /**
      * Value for {@link #EXTRA_AS_HEADS_UP}.
      * @hide
      */
@@ -2287,14 +2311,12 @@
 
             int N = mActions.size();
             if (N > 0) {
-                // Log.d("Notification", "has actions: " + mContentText);
                 big.setViewVisibility(R.id.actions, View.VISIBLE);
                 big.setViewVisibility(R.id.action_divider, View.VISIBLE);
                 if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS;
                 big.removeAllViews(R.id.actions);
                 for (int i=0; i<N; i++) {
                     final RemoteViews button = generateActionButton(mActions.get(i));
-                    //Log.d("Notification", "adding action " + i + ": " + mActions.get(i).title);
                     big.addView(R.id.actions, button);
                 }
             }
@@ -3003,4 +3025,142 @@
             return wip;
         }
     }
+
+    /**
+     * Notification style for media playback notifications.
+     *
+     * In the expanded form, {@link Notification#bigContentView}, up to 5
+     * {@link Notification.Action}s specified with
+     * {@link Notification.Builder#addAction(int, CharSequence, PendingIntent) addAction} will be
+     * shown as icon-only pushbuttons, suitable for transport controls. The Bitmap given to
+     * {@link Notification.Builder#setLargeIcon(android.graphics.Bitmap) setLargeIcon()} will be
+     * treated as album artwork.
+     *
+     * Unlike the other styles provided here, MediaStyle can also modify the standard-size
+     * {@link Notification#contentView}; by providing action indices to
+     * {@link #setShowActionsInCompactView(int...)} you can promote up to 2 actions to be displayed
+     * in the standard view alongside the usual content.
+     *
+     * Finally, if you attach a {@link android.media.session.MediaSessionToken} using
+     * {@link android.app.Notification.MediaStyle#setMediaSession(MediaSessionToken)},
+     * the System UI can identify this as a notification representing an active media session
+     * and respond accordingly (by showing album artwork in the lockscreen, for example).
+     *
+     * To use this style with your Notification, feed it to
+     * {@link Notification.Builder#setStyle(android.app.Notification.Style)} like so:
+     * <pre class="prettyprint">
+     * Notification noti = new Notification.Builder()
+     *     .setSmallIcon(R.drawable.ic_stat_player)
+     *     .setContentTitle(&quot;Track title&quot;)     // these three lines are optional
+     *     .setContentText(&quot;Artist - Album&quot;)   // if you use
+     *     .setLargeIcon(albumArtBitmap))      // setMediaSession(token, true)
+     *     .setMediaSession(mySession, true)
+     *     .setStyle(<b>new Notification.MediaStyle()</b>)
+     *     .build();
+     * </pre>
+     *
+     * @see Notification#bigContentView
+     */
+    public static class MediaStyle extends Style {
+        static final int MAX_MEDIA_BUTTONS_IN_COMPACT = 2;
+        static final int MAX_MEDIA_BUTTONS = 5;
+
+        private int[] mActionsToShowInCompact = null;
+        private MediaSessionToken mToken;
+
+        public MediaStyle() {
+        }
+
+        public MediaStyle(Builder builder) {
+            setBuilder(builder);
+        }
+
+        /**
+         * Request up to 2 actions (by index in the order of addition) to be shown in the compact
+         * notification view.
+         */
+        public MediaStyle setShowActionsInCompactView(int...actions) {
+            mActionsToShowInCompact = actions;
+            return this;
+        }
+
+        /**
+         * Attach a {@link android.media.session.MediaSessionToken} to this Notification to provide
+         * additional playback information and control to the SystemUI.
+         */
+        public MediaStyle setMediaSession(MediaSessionToken token) {
+            mToken = token;
+            return this;
+        }
+
+        @Override
+        public Notification buildStyled(Notification wip) {
+            wip.contentView = makeMediaContentView();
+            wip.bigContentView = makeMediaBigContentView();
+
+            return wip;
+        }
+
+        /** @hide */
+        @Override
+        public void addExtras(Bundle extras) {
+            super.addExtras(extras);
+
+            if (mToken != null) {
+                extras.putParcelable(EXTRA_MEDIA_SESSION, mToken);
+            }
+        }
+
+        private RemoteViews generateMediaActionButton(Action action) {
+            final boolean tombstone = (action.actionIntent == null);
+            RemoteViews button = new RemoteViews(mBuilder.mContext.getPackageName(),
+                    R.layout.notification_quantum_media_action);
+            button.setImageViewResource(R.id.action0, action.icon);
+            if (!tombstone) {
+                button.setOnClickPendingIntent(R.id.action0, action.actionIntent);
+            }
+            button.setContentDescription(R.id.action0, action.title);
+            return button;
+        }
+
+        private RemoteViews makeMediaContentView() {
+            RemoteViews view = mBuilder.applyStandardTemplate(
+                    R.layout.notification_template_quantum_media, true /* 1U */);
+
+            final int numActions = mBuilder.mActions.size();
+            final int N = mActionsToShowInCompact == null
+                    ? 0
+                    : Math.min(mActionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT);
+            if (N > 0) {
+                view.removeAllViews(R.id.actions);
+                for (int i = 0; i < N; i++) {
+                    if (i >= numActions) {
+                        throw new IllegalArgumentException(String.format(
+                                "setShowActionsInCompactView: action %d out of bounds (max %d)",
+                                i, numActions - 1));
+                    }
+
+                    final Action action = mBuilder.mActions.get(mActionsToShowInCompact[i]);
+                    final RemoteViews button = generateMediaActionButton(action);
+                    view.addView(R.id.actions, button);
+                }
+            }
+            return view;
+        }
+
+        private RemoteViews makeMediaBigContentView() {
+            RemoteViews big = mBuilder.applyStandardTemplate(
+                    R.layout.notification_template_quantum_big_media, false);
+
+            final int N = Math.min(mBuilder.mActions.size(), MAX_MEDIA_BUTTONS);
+            if (N > 0) {
+                big.removeAllViews(R.id.actions);
+                for (int i=0; i<N; i++) {
+                    final RemoteViews button = generateMediaActionButton(mBuilder.mActions.get(i));
+                    big.addView(R.id.actions, button);
+                }
+            }
+            return big;
+        }
+    }
 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 9e02e4b..d0ac9c9 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2069,6 +2069,9 @@
      *  <dt> {@link #WIFI_P2P_SERVICE} ("wifip2p")
      *  <dd> A {@link android.net.wifi.p2p.WifiP2pManager WifiP2pManager} for management of
      * Wi-Fi Direct connectivity.
+     *  <dt> {@link #ETHERNET_SERVICE} ("ethernet")
+     *  <dd> A {@link android.net.ethernet.EthernetManager EthernetManager} for
+     * management of Ethernet connectivity.
      * <dt> {@link #INPUT_METHOD_SERVICE} ("input_method")
      * <dd> An {@link android.view.inputmethod.InputMethodManager InputMethodManager}
      * for management of input methods.
@@ -2382,6 +2385,18 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a {@link
+     * android.net.ethernet.EthernetManager} for handling management of
+     * Ethernet access.
+     *
+     * @see #getSystemService
+     * @see android.net.ethernet.EthernetManager
+     *
+     * @hide
+     */
+    public static final String ETHERNET_SERVICE = "ethernet";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a {@link
      * android.net.nsd.NsdManager} for handling management of network service
      * discovery
      *
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 35c86e7..0705e0c 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -169,6 +169,10 @@
     private boolean mFaceDetectionRunning = false;
     private Object mAutoFocusCallbackLock = new Object();
 
+    private static final int NO_ERROR = 0;
+    private static final int EACCESS = -13;
+    private static final int ENODEV = -19;
+
     /**
      * Broadcast Action:  A new picture is taken by the camera, and the entry of
      * the picture has been added to the media store.
@@ -328,6 +332,24 @@
     }
 
     Camera(int cameraId) {
+        int err = cameraInit(cameraId);
+        if (checkInitErrors(err)) {
+            switch(err) {
+                case EACCESS:
+                    throw new RuntimeException("Fail to connect to camera service");
+                case ENODEV:
+                    throw new RuntimeException("Camera initialization failed");
+                default:
+                    // Should never hit this.
+                    throw new RuntimeException("Unknown camera error");
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public int cameraInit(int cameraId) {
         mShutterCallback = null;
         mRawImageCallback = null;
         mJpegCallback = null;
@@ -347,7 +369,21 @@
 
         String packageName = ActivityThread.currentPackageName();
 
-        native_setup(new WeakReference<Camera>(this), cameraId, packageName);
+        return native_setup(new WeakReference<Camera>(this), cameraId, packageName);
+    }
+
+    /**
+     * @hide
+     */
+    public static boolean checkInitErrors(int err) {
+        return err != NO_ERROR;
+    }
+
+    /**
+     * @hide
+     */
+    public static Camera openUninitialized() {
+        return new Camera();
     }
 
     /**
@@ -360,7 +396,7 @@
         release();
     }
 
-    private native final void native_setup(Object camera_this, int cameraId,
+    private native final int native_setup(Object camera_this, int cameraId,
                                            String packageName);
 
     private native final void native_release();
@@ -458,13 +494,16 @@
      */
     public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
         if (holder != null) {
-            setPreviewDisplay(holder.getSurface());
+            setPreviewSurface(holder.getSurface());
         } else {
-            setPreviewDisplay((Surface)null);
+            setPreviewSurface((Surface)null);
         }
     }
 
-    private native final void setPreviewDisplay(Surface surface) throws IOException;
+    /**
+     * @hide
+     */
+    public native final void setPreviewSurface(Surface surface) throws IOException;
 
     /**
      * Sets the {@link SurfaceTexture} to be used for live preview.
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 0fcd598..cb463a6 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -20,6 +20,7 @@
 import android.hardware.ICameraService;
 import android.hardware.ICameraServiceListener;
 import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.legacy.CameraDeviceUserShim;
 import android.hardware.camera2.utils.CameraBinderDecorator;
 import android.hardware.camera2.utils.CameraRuntimeException;
 import android.hardware.camera2.utils.BinderHolder;
@@ -194,7 +195,6 @@
             // impossible
             return null;
         }
-
         return new CameraCharacteristics(info);
     }
 
@@ -236,10 +236,23 @@
                                 handler);
 
                 BinderHolder holder = new BinderHolder();
-                mCameraService.connectDevice(device.getCallbacks(),
-                        Integer.parseInt(cameraId),
-                        mContext.getPackageName(), USE_CALLING_UID, holder);
-                cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
+
+                ICameraDeviceCallbacks callbacks = device.getCallbacks();
+                int id = Integer.parseInt(cameraId);
+                try {
+                    mCameraService.connectDevice(callbacks, id, mContext.getPackageName(),
+                            USE_CALLING_UID, holder);
+                    cameraUser = ICameraDeviceUser.Stub.asInterface(holder.getBinder());
+                } catch (CameraRuntimeException e) {
+                    if (e.getReason() == CameraAccessException.CAMERA_DEPRECATED_HAL) {
+                        // Use legacy camera implementation for HAL1 devices
+                        Log.i(TAG, "Using legacy camera HAL.");
+                        cameraUser = CameraDeviceUserShim.connectBinderShim(callbacks, id);
+                    } else {
+                        // Rethrow otherwise
+                        throw e;
+                    }
+                }
 
                 // TODO: factor out listener to be non-nested, then move setter to constructor
                 // For now, calling setRemoteDevice will fire initial
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index a70aa3b..54ffd6b 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -22,6 +22,8 @@
 import android.util.Rational;
 import android.view.Surface;
 
+import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Objects;
 
@@ -199,6 +201,20 @@
     }
 
     /**
+     * @hide
+     */
+    public boolean containsTarget(Surface surface) {
+        return mSurfaceSet.contains(surface);
+    }
+
+    /**
+     * @hide
+     */
+    public Collection<Surface> getTargets() {
+        return Collections.unmodifiableCollection(mSurfaceSet);
+    }
+
+    /**
      * A builder for capture requests.
      *
      * <p>To obtain a builder instance, use the
diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
index 0815170..50a58ed 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -26,7 +26,8 @@
 interface ICameraDeviceUser
 {
     /**
-     * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceUser.h
+     * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceUser.h and
+     * frameworks/base/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
      */
     void disconnect();
 
@@ -41,6 +42,27 @@
 
     int cancelRequest(int requestId, out LongParcelable lastFrameNumber);
 
+    /**
+     * Begin the device configuration.
+     *
+     * <p>
+     * beginConfigure must be called before any call to deleteStream, createStream,
+     * or endConfigure.  It is not valid to call this when the device is not idle.
+     * <p>
+     */
+    int beginConfigure();
+
+    /**
+     * End the device configuration.
+     *
+     * <p>
+     * endConfigure must be called after stream configuration is complete (i.e. after
+     * a call to beginConfigure and subsequent createStream/deleteStream calls).  This
+     * must be called before any requests can be submitted.
+     * <p>
+     */
+    int endConfigure();
+
     int deleteStream(int streamId);
 
     // non-negative value is the stream ID. negative value is status_t
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index dba24a1..e78ffff 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -216,7 +216,7 @@
             try {
                 waitUntilIdle();
 
-                // TODO: mRemoteDevice.beginConfigure
+                mRemoteDevice.beginConfigure();
                 // Delete all streams first (to free up HW resources)
                 for (Integer streamId : deleteList) {
                     mRemoteDevice.deleteStream(streamId);
@@ -231,7 +231,7 @@
                     mConfiguredOutputs.put(streamId, s);
                 }
 
-                // TODO: mRemoteDevice.endConfigure
+                mRemoteDevice.endConfigure();
             } catch (CameraRuntimeException e) {
                 if (e.getReason() == CAMERA_IN_USE) {
                     throw new IllegalStateException("The camera is currently busy." +
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index db7486d..27cfd38 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -63,7 +63,7 @@
     private static final String TAG = "CameraMetadataJV";
     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
     // this should be in sync with HAL_PIXEL_FORMAT_BLOB defined in graphics.h
-    private static final int NATIVE_JPEG_FORMAT = 0x21;
+    public static final int NATIVE_JPEG_FORMAT = 0x21;
 
     public CameraMetadataNative() {
         super();
diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
index b3a9559..7544045 100644
--- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
+++ b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
@@ -45,6 +45,15 @@
         readFromParcel(in);
     }
 
+    public CaptureResultExtras(int requestId, int subsequenceId, int afTriggerId,
+                               int precaptureTriggerId, long frameNumber) {
+        this.requestId = requestId;
+        this.subsequenceId = subsequenceId;
+        this.afTriggerId = afTriggerId;
+        this.precaptureTriggerId = precaptureTriggerId;
+        this.frameNumber = frameNumber;
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/core/java/android/hardware/camera2/legacy/BurstHolder.java b/core/java/android/hardware/camera2/legacy/BurstHolder.java
new file mode 100644
index 0000000..e35eb50
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/BurstHolder.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.legacy;
+
+import android.hardware.camera2.CaptureRequest;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Immutable container for a burst of capture results.
+ */
+public class BurstHolder {
+
+    private final ArrayList<CaptureRequest> mRequests;
+    private final boolean mRepeating;
+    private final int mRequestId;
+
+    /**
+     * Immutable container for a burst of capture results.
+     *
+     * @param requestId id of the burst request.
+     * @param repeating true if this burst is repeating.
+     * @param requests a {@link java.util.List} of {@link CaptureRequest}s in this burst.
+     */
+    public BurstHolder(int requestId, boolean repeating, List<CaptureRequest> requests) {
+        mRequests = new ArrayList<CaptureRequest>(requests);
+        mRepeating = repeating;
+        mRequestId = requestId;
+    }
+
+    /**
+     * Get the id of this request.
+     */
+    public int getRequestId() {
+        return mRequestId;
+    }
+
+    /**
+     * Return true if this repeating.
+     */
+    public boolean isRepeating() {
+        return mRepeating;
+    }
+
+    /**
+     * Return the number of requests in this burst sequence.
+     */
+    public int getNumberOfRequests() {
+        return mRequests.size();
+    }
+
+    /**
+     * Create a list of {@link RequestHolder} objects encapsulating the requests in this burst.
+     *
+     * @param frameNumber the starting framenumber for this burst.
+     * @return the list of {@link RequestHolder} objects.
+     */
+    public List<RequestHolder> produceRequestHolders(long frameNumber) {
+        ArrayList<RequestHolder> holders = new ArrayList<RequestHolder>();
+        int i = 0;
+        for (CaptureRequest r : mRequests) {
+            holders.add(new RequestHolder(mRequestId, i, r, mRepeating, frameNumber + i));
+            ++i;
+        }
+        return holders;
+    }
+}
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceState.java b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
new file mode 100644
index 0000000..71adf8b
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.legacy;
+
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.utils.CameraBinderDecorator;
+import android.os.Handler;
+import android.util.Log;
+
+/**
+ * Emulates a the state of a single Camera2 device.
+ *
+ * <p>
+ * This class acts as the state machine for a camera device.  Valid state transitions are given
+ * in the table below:
+ * </p>
+ *
+ * <ul>
+ *      <li>{@code UNCONFIGURED -> CONFIGURING}</li>
+ *      <li>{@code CONFIGURING -> IDLE}</li>
+ *      <li>{@code IDLE -> CONFIGURING}</li>
+ *      <li>{@code IDLE -> CAPTURING}</li>
+ *      <li>{@code CAPTURING -> IDLE}</li>
+ *      <li>{@code ANY -> ERROR}</li>
+ * </ul>
+ */
+public class CameraDeviceState {
+    private static final String TAG = "CameraDeviceState";
+    private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG);
+
+    private static final int STATE_ERROR = 0;
+    private static final int STATE_UNCONFIGURED = 1;
+    private static final int STATE_CONFIGURING = 2;
+    private static final int STATE_IDLE = 3;
+    private static final int STATE_CAPTURING = 4;
+
+    private int mCurrentState = STATE_UNCONFIGURED;
+    private int mCurrentError = CameraBinderDecorator.NO_ERROR;
+
+    private RequestHolder mCurrentRequest = null;
+
+    private Handler mCurrentHandler = null;
+    private CameraDeviceStateListener mCurrentListener = null;
+
+
+    /**
+     * CameraDeviceStateListener callbacks to be called after state transitions.
+     */
+    public interface CameraDeviceStateListener {
+        void onError(int errorCode, RequestHolder holder);
+        void onConfiguring();
+        void onIdle();
+        void onCaptureStarted(RequestHolder holder);
+        void onCaptureResult(CameraMetadataNative result, RequestHolder holder);
+    }
+
+    /**
+     * Transition to the {@code ERROR} state.
+     *
+     * <p>
+     * The device cannot exit the {@code ERROR} state.  If the device was not already in the
+     * {@code ERROR} state, {@link CameraDeviceStateListener#onError(int, RequestHolder)} will be
+     * called.
+     * </p>
+     *
+     * @param error the error to set.  Should be one of the error codes defined in
+     *      {@link android.hardware.camera2.utils.CameraBinderDecorator}.
+     */
+    public synchronized void setError(int error) {
+        mCurrentError = error;
+        doStateTransition(STATE_ERROR);
+    }
+
+    /**
+     * Transition to the {@code CONFIGURING} state, or {@code ERROR} if in an invalid state.
+     *
+     * <p>
+     * If the device was not already in the {@code CONFIGURING} state,
+     * {@link CameraDeviceStateListener#onConfiguring()} will be called.
+     * </p>
+     *
+     * @returns {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+     */
+    public synchronized int setConfiguring() {
+        doStateTransition(STATE_CONFIGURING);
+        return mCurrentError;
+    }
+
+    /**
+     * Transition to the {@code IDLE} state, or {@code ERROR} if in an invalid state.
+     *
+     * <p>
+     * If the device was not already in the {@code IDLE} state,
+     * {@link CameraDeviceStateListener#onIdle()} will be called.
+     * </p>
+     *
+     * @returns {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+     */
+    public synchronized int setIdle() {
+        doStateTransition(STATE_IDLE);
+        return mCurrentError;
+    }
+
+    /**
+     * Transition to the {@code CAPTURING} state, or {@code ERROR} if in an invalid state.
+     *
+     * <p>
+     * If the device was not already in the {@code CAPTURING} state,
+     * {@link CameraDeviceStateListener#onCaptureStarted(RequestHolder)} will be called.
+     * </p>
+     *
+     * @param request A {@link RequestHolder} containing the request for the current capture.
+     * @returns {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+     */
+    public synchronized int setCaptureStart(final RequestHolder request) {
+        mCurrentRequest = request;
+        doStateTransition(STATE_CAPTURING);
+        return mCurrentError;
+    }
+
+    /**
+     * Set the result for a capture.
+     *
+     * <p>
+     * If the device was in the {@code CAPTURING} state,
+     * {@link CameraDeviceStateListener#onCaptureResult(CameraMetadataNative, RequestHolder)} will
+     * be called with the given result, otherwise this will result in the device transitioning to
+     * the {@code ERROR} state,
+     * </p>
+     *
+     * @param request the {@link RequestHolder} request that created this result.
+     * @param result the {@link CameraMetadataNative} result to set.
+     * @returns {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+     */
+    public synchronized int setCaptureResult(final RequestHolder request,
+                                             final CameraMetadataNative result) {
+        if (mCurrentState != STATE_CAPTURING) {
+            Log.e(TAG, "Cannot receive result while in state: " + mCurrentState);
+            mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
+            doStateTransition(STATE_ERROR);
+            return mCurrentError;
+        }
+
+        if (mCurrentHandler != null && mCurrentListener != null) {
+            mCurrentHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCurrentListener.onCaptureResult(result, request);
+                }
+            });
+        }
+        return mCurrentError;
+    }
+
+    /**
+     * Set the listener for state transition callbacks.
+     *
+     * @param handler handler on which to call the callbacks.
+     * @param listener the {@link CameraDeviceStateListener} callbacks to call.
+     */
+    public synchronized void setCameraDeviceCallbacks(Handler handler,
+                                                      CameraDeviceStateListener listener) {
+        mCurrentHandler = handler;
+        mCurrentListener = listener;
+    }
+
+    private void doStateTransition(int newState) {
+        if (DEBUG) {
+            if (newState != mCurrentState) {
+                Log.d(TAG, "Transitioning to state " + newState);
+            }
+        }
+        switch(newState) {
+            case STATE_ERROR:
+                if (mCurrentState != STATE_ERROR && mCurrentHandler != null &&
+                        mCurrentListener != null) {
+                    mCurrentHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            mCurrentListener.onError(mCurrentError, mCurrentRequest);
+                        }
+                    });
+                }
+                mCurrentState = STATE_ERROR;
+                break;
+            case STATE_CONFIGURING:
+                if (mCurrentState != STATE_UNCONFIGURED && mCurrentState != STATE_IDLE) {
+                    Log.e(TAG, "Cannot call configure while in state: " + mCurrentState);
+                    mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
+                    doStateTransition(STATE_ERROR);
+                    break;
+                }
+                if (mCurrentState != STATE_CONFIGURING && mCurrentHandler != null &&
+                        mCurrentListener != null) {
+                    mCurrentHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            mCurrentListener.onConfiguring();
+                        }
+                    });
+                }
+                mCurrentState = STATE_CONFIGURING;
+                break;
+            case STATE_IDLE:
+                if (mCurrentState != STATE_CONFIGURING && mCurrentState != STATE_CAPTURING) {
+                    Log.e(TAG, "Cannot call idle while in state: " + mCurrentState);
+                    mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
+                    doStateTransition(STATE_ERROR);
+                    break;
+                }
+                if (mCurrentState != STATE_IDLE && mCurrentHandler != null &&
+                        mCurrentListener != null) {
+                    mCurrentHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            mCurrentListener.onIdle();
+                        }
+                    });
+                }
+                mCurrentState = STATE_IDLE;
+                break;
+            case STATE_CAPTURING:
+                if (mCurrentState != STATE_IDLE && mCurrentState != STATE_CAPTURING) {
+                    Log.e(TAG, "Cannot call capture while in state: " + mCurrentState);
+                    mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
+                    doStateTransition(STATE_ERROR);
+                    break;
+                }
+                if (mCurrentHandler != null && mCurrentListener != null) {
+                    mCurrentHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            mCurrentListener.onCaptureStarted(mCurrentRequest);
+                        }
+                    });
+                }
+                mCurrentState = STATE_CAPTURING;
+                break;
+            default:
+                throw new IllegalStateException("Transition to unknown state: " + newState);
+        }
+    }
+
+
+}
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
new file mode 100644
index 0000000..54d9c3c
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.legacy;
+
+import android.hardware.Camera;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.ICameraDeviceCallbacks;
+import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.utils.CameraBinderDecorator;
+import android.hardware.camera2.utils.CameraRuntimeException;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.Surface;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Compatibility implementation of the Camera2 API binder interface.
+ *
+ * <p>
+ * This is intended to be called from the same process as client
+ * {@link android.hardware.camera2.CameraDevice}, and wraps a
+ * {@link android.hardware.camera2.legacy.LegacyCameraDevice} that emulates Camera2 service using
+ * the Camera1 API.
+ * </p>
+ *
+ * <p>
+ * Keep up to date with ICameraDeviceUser.aidl.
+ * </p>
+ */
+public class CameraDeviceUserShim implements ICameraDeviceUser {
+    private static final String TAG = "CameraDeviceUserShim";
+
+    private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG);
+
+    private final LegacyCameraDevice mLegacyDevice;
+
+    private final Object mConfigureLock = new Object();
+    private int mSurfaceIdCounter;
+    private boolean mConfiguring;
+    private final SparseArray<Surface> mSurfaces;
+
+    protected CameraDeviceUserShim(int cameraId, LegacyCameraDevice legacyCamera) {
+        mLegacyDevice = legacyCamera;
+        mConfiguring = false;
+        mSurfaces = new SparseArray<Surface>();
+
+        mSurfaceIdCounter = 0;
+    }
+
+    public static CameraDeviceUserShim connectBinderShim(ICameraDeviceCallbacks callbacks,
+                                                         int cameraId) {
+        if (DEBUG) {
+            Log.d(TAG, "Opening shim Camera device");
+        }
+        // TODO: Move open/init into LegacyCameraDevice thread when API is switched to async.
+        Camera legacyCamera = Camera.openUninitialized();
+        int initErrors = legacyCamera.cameraInit(cameraId);
+        // Check errors old HAL initialization
+        if (Camera.checkInitErrors(initErrors)) {
+            // TODO: Map over old camera error codes.  This likely involves improving the error
+            // reporting in the HAL1 connect path.
+            throw new CameraRuntimeException(CameraAccessException.CAMERA_DISCONNECTED);
+        }
+        LegacyCameraDevice device = new LegacyCameraDevice(cameraId, legacyCamera, callbacks);
+        return new CameraDeviceUserShim(cameraId, device);
+    }
+
+    @Override
+    public void disconnect() {
+        if (DEBUG) {
+            Log.d(TAG, "disconnect called.");
+        }
+        mLegacyDevice.close();
+    }
+
+    @Override
+    public int submitRequest(CaptureRequest request, boolean streaming,
+                             /*out*/LongParcelable lastFrameNumber) {
+        if (DEBUG) {
+            Log.d(TAG, "submitRequest called.");
+        }
+        synchronized(mConfigureLock) {
+            if (mConfiguring) {
+                Log.e(TAG, "Cannot submit request, configuration change in progress.");
+                return CameraBinderDecorator.INVALID_OPERATION;
+            }
+        }
+        return mLegacyDevice.submitRequest(request, streaming, lastFrameNumber);
+    }
+
+    @Override
+    public int submitRequestList(List<CaptureRequest> request, boolean streaming,
+                                 /*out*/LongParcelable lastFrameNumber) {
+        if (DEBUG) {
+            Log.d(TAG, "submitRequestList called.");
+        }
+        synchronized(mConfigureLock) {
+            if (mConfiguring) {
+                Log.e(TAG, "Cannot submit request, configuration change in progress.");
+                return CameraBinderDecorator.INVALID_OPERATION;
+            }
+        }
+        return mLegacyDevice.submitRequestList(request, streaming, lastFrameNumber);
+    }
+
+    @Override
+    public int cancelRequest(int requestId, /*out*/LongParcelable lastFrameNumber) {
+        if (DEBUG) {
+            Log.d(TAG, "cancelRequest called.");
+        }
+        synchronized(mConfigureLock) {
+            if (mConfiguring) {
+                Log.e(TAG, "Cannot cancel request, configuration change in progress.");
+                return CameraBinderDecorator.INVALID_OPERATION;
+            }
+        }
+        long lastFrame = mLegacyDevice.cancelRequest(requestId);
+        lastFrameNumber.setNumber(lastFrame);
+        return CameraBinderDecorator.NO_ERROR;
+    }
+
+    @Override
+    public int beginConfigure() {
+        if (DEBUG) {
+            Log.d(TAG, "beginConfigure called.");
+        }
+        synchronized(mConfigureLock) {
+            if (mConfiguring) {
+                Log.e(TAG, "Cannot begin configure, configuration change already in progress.");
+                return CameraBinderDecorator.INVALID_OPERATION;
+            }
+            mConfiguring = true;
+        }
+        return CameraBinderDecorator.NO_ERROR;
+    }
+
+    @Override
+    public int endConfigure() {
+        if (DEBUG) {
+            Log.d(TAG, "endConfigure called.");
+        }
+        ArrayList<Surface> surfaces = null;
+        synchronized(mConfigureLock) {
+            if (!mConfiguring) {
+                Log.e(TAG, "Cannot end configure, no configuration change in progress.");
+                return CameraBinderDecorator.INVALID_OPERATION;
+            }
+            int numSurfaces = mSurfaces.size();
+            if (numSurfaces > 0) {
+                surfaces = new ArrayList<Surface>();
+                for (int i = 0; i < numSurfaces; ++i) {
+                    surfaces.add(mSurfaces.valueAt(i));
+                }
+            }
+            mConfiguring = false;
+        }
+        return mLegacyDevice.configureOutputs(surfaces);
+    }
+
+    @Override
+    public int deleteStream(int streamId) {
+        if (DEBUG) {
+            Log.d(TAG, "deleteStream called.");
+        }
+        synchronized(mConfigureLock) {
+            if (!mConfiguring) {
+                Log.e(TAG, "Cannot delete stream, beginConfigure hasn't been called yet.");
+                return CameraBinderDecorator.INVALID_OPERATION;
+            }
+            int index = mSurfaces.indexOfKey(streamId);
+            if (index < 0) {
+                Log.e(TAG, "Cannot delete stream, stream id " + streamId + " doesn't exist.");
+                return CameraBinderDecorator.BAD_VALUE;
+            }
+            mSurfaces.removeAt(index);
+        }
+        return CameraBinderDecorator.NO_ERROR;
+    }
+
+    @Override
+    public int createStream(int width, int height, int format, Surface surface) {
+        if (DEBUG) {
+            Log.d(TAG, "createStream called.");
+        }
+        synchronized(mConfigureLock) {
+            if (!mConfiguring) {
+                Log.e(TAG, "Cannot create stream, beginConfigure hasn't been called yet.");
+                return CameraBinderDecorator.INVALID_OPERATION;
+            }
+            int id = ++mSurfaceIdCounter;
+            mSurfaces.put(id, surface);
+            return id;
+        }
+    }
+
+    @Override
+    public int createDefaultRequest(int templateId, /*out*/CameraMetadataNative request) {
+        if (DEBUG) {
+            Log.d(TAG, "createDefaultRequest called.");
+        }
+        // TODO: implement createDefaultRequest.
+        Log.e(TAG, "createDefaultRequest unimplemented.");
+        return CameraBinderDecorator.NO_ERROR;
+    }
+
+    @Override
+    public int getCameraInfo(/*out*/CameraMetadataNative info) {
+        if (DEBUG) {
+            Log.d(TAG, "getCameraInfo called.");
+        }
+        // TODO: implement getCameraInfo.
+        Log.e(TAG, "getCameraInfo unimplemented.");
+        return CameraBinderDecorator.NO_ERROR;
+    }
+
+    @Override
+    public int waitUntilIdle() throws RemoteException {
+        if (DEBUG) {
+            Log.d(TAG, "waitUntilIdle called.");
+        }
+        synchronized(mConfigureLock) {
+            if (mConfiguring) {
+                Log.e(TAG, "Cannot wait until idle, configuration change in progress.");
+                return CameraBinderDecorator.INVALID_OPERATION;
+            }
+        }
+        mLegacyDevice.waitUntilIdle();
+        return CameraBinderDecorator.NO_ERROR;
+    }
+
+    @Override
+    public int flush(/*out*/LongParcelable lastFrameNumber) {
+        if (DEBUG) {
+            Log.d(TAG, "flush called.");
+        }
+        synchronized(mConfigureLock) {
+            if (mConfiguring) {
+                Log.e(TAG, "Cannot flush, configuration change in progress.");
+                return CameraBinderDecorator.INVALID_OPERATION;
+            }
+        }
+        // TODO: implement flush.
+        return CameraBinderDecorator.NO_ERROR;
+    }
+
+    @Override
+    public IBinder asBinder() {
+        // This is solely intended to be used for in-process binding.
+        return null;
+    }
+}
diff --git a/core/java/android/hardware/camera2/legacy/GLThreadManager.java b/core/java/android/hardware/camera2/legacy/GLThreadManager.java
new file mode 100644
index 0000000..3fd2309
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/GLThreadManager.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.legacy;
+
+import android.graphics.SurfaceTexture;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.Surface;
+
+import java.util.Collection;
+
+/**
+ * GLThreadManager handles the thread used for rendering into the configured output surfaces.
+ */
+public class GLThreadManager {
+    private final String TAG;
+    private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG);
+
+    private static final int MSG_NEW_CONFIGURATION = 1;
+    private static final int MSG_NEW_FRAME = 2;
+    private static final int MSG_CLEANUP = 3;
+    private static final int MSG_DROP_FRAMES = 4;
+    private static final int MSG_ALLOW_FRAMES = 5;
+
+    private final SurfaceTextureRenderer mTextureRenderer;
+
+    private final RequestHandlerThread mGLHandlerThread;
+
+    private final RequestThreadManager.FpsCounter mPrevCounter =
+            new RequestThreadManager.FpsCounter("GL Preview Producer");
+
+    /**
+     * Container object for Configure messages.
+     */
+    private static class ConfigureHolder {
+        public final ConditionVariable condition;
+        public final Collection<Surface> surfaces;
+
+        public ConfigureHolder(ConditionVariable condition, Collection<Surface> surfaces) {
+            this.condition = condition;
+            this.surfaces = surfaces;
+        }
+    }
+
+    private final Handler.Callback mGLHandlerCb = new Handler.Callback() {
+        private boolean mCleanup = false;
+        private boolean mConfigured = false;
+        private boolean mDroppingFrames = false;
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public boolean handleMessage(Message msg) {
+            if (mCleanup) {
+                return true;
+            }
+            switch (msg.what) {
+                case MSG_NEW_CONFIGURATION:
+                    ConfigureHolder configure = (ConfigureHolder) msg.obj;
+                    mTextureRenderer.cleanupEGLContext();
+                    mTextureRenderer.configureSurfaces(configure.surfaces);
+                    configure.condition.open();
+                    mConfigured = true;
+                    break;
+                case MSG_NEW_FRAME:
+                    if (mDroppingFrames) {
+                        Log.w(TAG, "Ignoring frame.");
+                        break;
+                    }
+                    if (DEBUG) {
+                        mPrevCounter.countAndLog();
+                    }
+                    if (!mConfigured) {
+                        Log.e(TAG, "Dropping frame, EGL context not configured!");
+                    }
+                    mTextureRenderer.drawIntoSurfaces((Collection<Surface>) msg.obj);
+                    break;
+                case MSG_CLEANUP:
+                    mTextureRenderer.cleanupEGLContext();
+                    mCleanup = true;
+                    mConfigured = false;
+                    break;
+                case MSG_DROP_FRAMES:
+                    mDroppingFrames = true;
+                    break;
+                case MSG_ALLOW_FRAMES:
+                    mDroppingFrames = false;
+                default:
+                    Log.e(TAG, "Unhandled message " + msg.what + " on GLThread.");
+                    break;
+            }
+            return true;
+        }
+    };
+
+    /**
+     * Create a new GL thread and renderer.
+     *
+     * @param cameraId the camera id for this thread.
+     */
+    public GLThreadManager(int cameraId) {
+        mTextureRenderer = new SurfaceTextureRenderer();
+        TAG = String.format("CameraDeviceGLThread-%d", cameraId);
+        mGLHandlerThread = new RequestHandlerThread(TAG, mGLHandlerCb);
+    }
+
+    /**
+     * Start the thread.
+     *
+     * <p>
+     * This must be called before queueing new frames.
+     * </p>
+     */
+    public void start() {
+        mGLHandlerThread.start();
+    }
+
+    /**
+     * Wait until the thread has started.
+     */
+    public void waitUntilStarted() {
+        mGLHandlerThread.waitUntilStarted();
+    }
+
+    /**
+     * Quit the thread.
+     *
+     * <p>
+     * No further methods can be called after this.
+     * </p>
+     */
+    public void quit() {
+        Handler handler = mGLHandlerThread.getHandler();
+        handler.sendMessageAtFrontOfQueue(handler.obtainMessage(MSG_CLEANUP));
+        mGLHandlerThread.quitSafely();
+    }
+
+    /**
+     * Queue a new call to draw into a given set of surfaces.
+     *
+     * <p>
+     * The set of surfaces passed here must be a subset of the set of surfaces passed in
+     * the last call to {@link #setConfigurationAndWait}.
+     * </p>
+     *
+     * @param targets a collection of {@link android.view.Surface}s to draw into.
+     */
+    public void queueNewFrame(Collection<Surface> targets) {
+        Handler handler = mGLHandlerThread.getHandler();
+
+        /**
+         * Avoid queuing more than one new frame.  If we are not consuming faster than frames
+         * are produced, drop frames rather than allowing the queue to back up.
+         */
+        if (!handler.hasMessages(MSG_NEW_FRAME)) {
+            handler.sendMessage(handler.obtainMessage(MSG_NEW_FRAME, targets));
+        } else {
+            Log.e(TAG, "GLThread dropping frame.  Not consuming frames quickly enough!");
+        }
+    }
+
+    /**
+     * Configure the GL renderer for the given set of output surfaces, and block until
+     * this configuration has been applied.
+     *
+     * @param surfaces a collection of {@link android.view.Surface}s to configure.
+     */
+    public void setConfigurationAndWait(Collection<Surface> surfaces) {
+        Handler handler = mGLHandlerThread.getHandler();
+
+        final ConditionVariable condition = new ConditionVariable(/*closed*/false);
+        ConfigureHolder configure = new ConfigureHolder(condition, surfaces);
+
+        Message m = handler.obtainMessage(MSG_NEW_CONFIGURATION, /*arg1*/0, /*arg2*/0, configure);
+        handler.sendMessage(m);
+
+        // Block until configuration applied.
+        condition.block();
+    }
+
+    /**
+     * Get the underlying surface to produce frames from.
+     *
+     * <p>
+     * This returns the surface that is drawn into the set of surfaces passed in for each frame.
+     * This method should only be called after a call to
+     * {@link #setConfigurationAndWait(java.util.Collection)}.  Calling this before the first call
+     * to {@link #setConfigurationAndWait(java.util.Collection)}, after {@link #quit()}, or
+     * concurrently to one of these calls may result in an invalid
+     * {@link android.graphics.SurfaceTexture} being returned.
+     * </p>
+     *
+     * @return an {@link android.graphics.SurfaceTexture} to draw to.
+     */
+    public SurfaceTexture getCurrentSurfaceTexture() {
+        return mTextureRenderer.getSurfaceTexture();
+    }
+
+    /**
+     * Ignore any subsequent calls to {@link #queueNewFrame(java.util.Collection)}.
+     */
+    public void ignoreNewFrames() {
+        mGLHandlerThread.getHandler().sendEmptyMessage(MSG_DROP_FRAMES);
+    }
+
+    /**
+     * Wait until no messages are queued.
+     */
+    public void waitUntilIdle() {
+        mGLHandlerThread.waitUntilIdle();
+    }
+
+    /**
+     * Re-enable drawing new frames after a call to {@link #ignoreNewFrames()}.
+     */
+    public void allowNewFrames() {
+        mGLHandlerThread.getHandler().sendEmptyMessage(MSG_ALLOW_FRAMES);
+    }
+}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
new file mode 100644
index 0000000..f9cf905
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.legacy;
+
+import android.graphics.ImageFormat;
+import android.hardware.Camera;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.impl.CaptureResultExtras;
+import android.hardware.camera2.ICameraDeviceCallbacks;
+import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.utils.CameraBinderDecorator;
+import android.hardware.camera2.utils.CameraRuntimeException;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Surface;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class emulates the functionality of a Camera2 device using a the old Camera class.
+ *
+ * <p>
+ * There are two main components that are used to implement this:
+ * - A state machine containing valid Camera2 device states ({@link CameraDeviceState}).
+ * - A message-queue based pipeline that manages an old Camera class, and executes capture and
+ *   configuration requests.
+ * </p>
+ */
+public class LegacyCameraDevice implements AutoCloseable {
+    public static final String DEBUG_PROP = "HAL1ShimLogging";
+
+    private final String TAG;
+
+    private final int mCameraId;
+    private final ICameraDeviceCallbacks mDeviceCallbacks;
+    private final CameraDeviceState mDeviceState = new CameraDeviceState();
+
+    private final ConditionVariable mIdle = new ConditionVariable(/*open*/true);
+    private final AtomicInteger mRequestIdCounter = new AtomicInteger(0);
+
+    private final HandlerThread mCallbackHandlerThread = new HandlerThread("ResultThread");
+    private final Handler mCallbackHandler;
+    private static final int ILLEGAL_VALUE = -1;
+
+    private CaptureResultExtras getExtrasFromRequest(RequestHolder holder) {
+        if (holder == null) {
+            return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE,
+                    ILLEGAL_VALUE, ILLEGAL_VALUE);
+        }
+        return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(),
+                /*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber());
+    }
+
+    /**
+     * Listener for the camera device state machine.  Calls the appropriate
+     * {@link ICameraDeviceCallbacks} for each state transition.
+     */
+    private final CameraDeviceState.CameraDeviceStateListener mStateListener =
+            new CameraDeviceState.CameraDeviceStateListener() {
+        @Override
+        public void onError(final int errorCode, RequestHolder holder) {
+            mIdle.open();
+            final CaptureResultExtras extras = getExtrasFromRequest(holder);
+            try {
+                mDeviceCallbacks.onCameraError(errorCode, extras);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Received remote exception during onCameraError callback: ", e);
+            }
+
+        }
+
+        @Override
+        public void onConfiguring() {
+            // Do nothing
+        }
+
+        @Override
+        public void onIdle() {
+            mIdle.open();
+
+            try {
+                mDeviceCallbacks.onCameraIdle();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Received remote exception during onCameraIdle callback: ", e);
+            }
+        }
+
+        @Override
+        public void onCaptureStarted(RequestHolder holder) {
+            final CaptureResultExtras extras = getExtrasFromRequest(holder);
+
+            try {
+                // TODO: Don't fake timestamp
+                mDeviceCallbacks.onCaptureStarted(extras, System.nanoTime());
+            } catch (RemoteException e) {
+                Log.e(TAG, "Received remote exception during onCameraError callback: ", e);
+            }
+
+        }
+
+        @Override
+        public void onCaptureResult(CameraMetadataNative result, RequestHolder holder) {
+            final CaptureResultExtras extras = getExtrasFromRequest(holder);
+
+            try {
+                // TODO: Don't fake metadata
+                mDeviceCallbacks.onResultReceived(result, extras);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Received remote exception during onCameraError callback: ", e);
+            }
+        }
+    };
+
+    private final RequestThreadManager mRequestThreadManager;
+
+    /**
+     * Check if a given surface uses {@link ImageFormat#YUV_420_888} format.
+     *
+     * @param s the surface to check.
+     * @return {@code true} if the surfaces uses {@link ImageFormat#YUV_420_888}.
+     */
+    static boolean needsConversion(Surface s) {
+        return LegacyCameraDevice.nativeDetectSurfaceType(s) == ImageFormat.YUV_420_888;
+    }
+
+    /**
+     * Create a new emulated camera device from a given Camera 1 API camera.
+     *
+     * <p>
+     * The {@link Camera} provided to this constructor must already have been successfully opened,
+     * and ownership of the provided camera is passed to this object.  No further calls to the
+     * camera methods should be made following this constructor.
+     * </p>
+     *
+     * @param cameraId the id of the camera.
+     * @param camera an open {@link Camera} device.
+     * @param callbacks {@link ICameraDeviceCallbacks} callbacks to call for Camera2 API operations.
+     */
+    public LegacyCameraDevice(int cameraId, Camera camera, ICameraDeviceCallbacks callbacks) {
+        mCameraId = cameraId;
+        mDeviceCallbacks = callbacks;
+        TAG = String.format("CameraDevice-%d-LE", mCameraId);
+
+        mCallbackHandlerThread.start();
+        mCallbackHandler = new Handler(mCallbackHandlerThread.getLooper());
+        mDeviceState.setCameraDeviceCallbacks(mCallbackHandler, mStateListener);
+        mRequestThreadManager =
+                new RequestThreadManager(cameraId, camera, mDeviceState);
+        mRequestThreadManager.start();
+    }
+
+    /**
+     * Configure the device with a set of output surfaces.
+     *
+     * @param outputs a list of surfaces to set.
+     * @return an error code for this binder operation, or {@link CameraBinderDecorator.NO_ERROR}
+     *          on success.
+     */
+    public int configureOutputs(List<Surface> outputs) {
+        int error = mDeviceState.setConfiguring();
+        if (error == CameraBinderDecorator.NO_ERROR) {
+            mRequestThreadManager.configure(outputs);
+            error = mDeviceState.setIdle();
+        }
+        return error;
+    }
+
+    /**
+     * Submit a burst of capture requests.
+     *
+     * @param requestList a list of capture requests to execute.
+     * @param repeating {@code true} if this burst is repeating.
+     * @param frameNumber an output argument that contains either the frame number of the last frame
+     *                    that will be returned for this request, or the frame number of the last
+     *                    frame that will be returned for the current repeating request if this
+     *                    burst is set to be repeating.
+     * @return the request id.
+     */
+    public int submitRequestList(List<CaptureRequest> requestList, boolean repeating,
+            /*out*/LongParcelable frameNumber) {
+        // TODO: validate request here
+        mIdle.close();
+        return mRequestThreadManager.submitCaptureRequests(requestList, repeating,
+                frameNumber);
+    }
+
+    /**
+     * Submit a single capture request.
+     *
+     * @param request the capture request to execute.
+     * @param repeating {@code true} if this request is repeating.
+     * @param frameNumber an output argument that contains either the frame number of the last frame
+     *                    that will be returned for this request, or the frame number of the last
+     *                    frame that will be returned for the current repeating request if this
+     *                    request is set to be repeating.
+     * @return the request id.
+     */
+    public int submitRequest(CaptureRequest request, boolean repeating,
+            /*out*/LongParcelable frameNumber) {
+        ArrayList<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
+        requestList.add(request);
+        return submitRequestList(requestList, repeating, frameNumber);
+    }
+
+    /**
+     * Cancel the repeating request with the given request id.
+     *
+     * @param requestId the request id of the request to cancel.
+     * @return the last frame number to be returned from the HAL for the given repeating request, or
+     *          {@code INVALID_FRAME} if none exists.
+     */
+    public long cancelRequest(int requestId) {
+        return mRequestThreadManager.cancelRepeating(requestId);
+    }
+
+    /**
+     * Block until the {@link ICameraDeviceCallbacks#onCameraIdle()} callback is received.
+     */
+    public void waitUntilIdle()  {
+        mIdle.block();
+    }
+
+    @Override
+    public void close() {
+        mRequestThreadManager.quit();
+        mCallbackHandlerThread.quitSafely();
+        // TODO: throw IllegalStateException in every method after close has been called
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } catch (CameraRuntimeException e) {
+            Log.e(TAG, "Got error while trying to finalize, ignoring: " + e.getMessage());
+        } finally {
+            super.finalize();
+        }
+    }
+
+    protected static native int nativeDetectSurfaceType(Surface surface);
+
+    protected static native void nativeDetectSurfaceDimens(Surface surface, int[] dimens);
+
+    protected static native void nativeConfigureSurface(Surface surface, int width, int height,
+                                                        int pixelFormat);
+
+    protected static native void nativeProduceFrame(Surface surface, byte[] pixelBuffer, int width,
+                                                    int height, int pixelFormat);
+
+    protected static native void nativeSetSurfaceFormat(Surface surface, int pixelFormat);
+
+    protected static native void nativeSetSurfaceDimens(Surface surface, int width, int height);
+
+}
diff --git a/core/java/android/hardware/camera2/legacy/RequestHandlerThread.java b/core/java/android/hardware/camera2/legacy/RequestHandlerThread.java
new file mode 100644
index 0000000..36cd907
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/RequestHandlerThread.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.legacy;
+
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.MessageQueue;
+
+public class RequestHandlerThread extends HandlerThread {
+    private final ConditionVariable mStarted = new ConditionVariable(false);
+    private final ConditionVariable mIdle = new ConditionVariable(true);
+    private Handler.Callback mCallback;
+    private volatile Handler mHandler;
+
+    public RequestHandlerThread(String name, Handler.Callback callback) {
+        super(name, Thread.MAX_PRIORITY);
+        mCallback = callback;
+    }
+
+    @Override
+    protected void onLooperPrepared() {
+        mHandler = new Handler(getLooper(), mCallback);
+        mStarted.open();
+    }
+
+    // Blocks until thread has started
+    public void waitUntilStarted() {
+        mStarted.block();
+    }
+
+    // May return null if the handler is not set up yet.
+    public Handler getHandler() {
+        return mHandler;
+    }
+
+    // Blocks until thread has started
+    public Handler waitAndGetHandler() {
+        waitUntilStarted();
+        return getHandler();
+    }
+
+    // Atomic multi-type message existence check
+    public boolean hasAnyMessages(int[] what) {
+        synchronized (mHandler.getLooper().getQueue()) {
+            for (int i : what) {
+                if (mHandler.hasMessages(i)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    // Atomic multi-type message remove
+    public void removeMessages(int[] what) {
+        synchronized (mHandler.getLooper().getQueue()) {
+            for (int i : what) {
+                mHandler.removeMessages(i);
+            }
+        }
+    }
+
+    private final MessageQueue.IdleHandler mIdleHandler = new MessageQueue.IdleHandler() {
+        @Override
+        public boolean queueIdle() {
+            mIdle.open();
+            return false;
+        }
+    };
+
+    // Blocks until thread is idling
+    public void waitUntilIdle() {
+        Looper looper = waitAndGetHandler().getLooper();
+        if (looper.isIdling()) {
+            return;
+        }
+        mIdle.close();
+        looper.getQueue().addIdleHandler(mIdleHandler);
+        if (looper.isIdling()) {
+            return;
+        }
+        mIdle.block();
+    }
+
+}
diff --git a/core/java/android/hardware/camera2/legacy/RequestHolder.java b/core/java/android/hardware/camera2/legacy/RequestHolder.java
new file mode 100644
index 0000000..8a9052f
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/RequestHolder.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.legacy;
+
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.view.Surface;
+
+import java.util.Collection;
+
+/**
+ * Immutable container for a single capture request and associated information.
+ */
+public class RequestHolder {
+
+    private final boolean mRepeating;
+    private final CaptureRequest mRequest;
+    private final int mRequestId;
+    private final int mSubsequeceId;
+    private final long mFrameNumber;
+
+    RequestHolder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating,
+                  long frameNumber) {
+        mRepeating = repeating;
+        mRequest = request;
+        mRequestId = requestId;
+        mSubsequeceId = subsequenceId;
+        mFrameNumber = frameNumber;
+    }
+
+    /**
+     * Return the request id for the contained {@link CaptureRequest}.
+     */
+    public int getRequestId() {
+        return mRequestId;
+    }
+
+    /**
+     * Returns true if the contained request is repeating.
+     */
+    public boolean isRepeating() {
+        return mRepeating;
+    }
+
+    /**
+     * Return the subsequence id for this request.
+     */
+    public int getSubsequeceId() {
+        return mSubsequeceId;
+    }
+
+    /**
+     * Returns the frame number for this request.
+     */
+    public long getFrameNumber() {
+        return mFrameNumber;
+    }
+
+    /**
+     * Returns the contained request.
+     */
+    public CaptureRequest getRequest() {
+        return mRequest;
+    }
+
+    /**
+     * Returns a read-only collection of the surfaces targeted by the contained request.
+     */
+    public Collection<Surface> getHolderTargets() {
+        return getRequest().getTargets();
+    }
+
+    /**
+     * Returns true if any of the surfaces targeted by the contained request require jpeg buffers.
+     */
+    public boolean hasJpegTargets() {
+        for (Surface s : getHolderTargets()) {
+            if (jpegType(s)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if any of the surfaces targeted by the contained request require a
+     * non-jpeg buffer type.
+     */
+    public boolean hasPreviewTargets() {
+        for (Surface s : getHolderTargets()) {
+            if (previewType(s)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return the first surface targeted by the contained request that requires a
+     * non-jpeg buffer type.
+     */
+    public Surface getFirstPreviewTarget() {
+        for (Surface s : getHolderTargets()) {
+            if (previewType(s)) {
+                return s;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns true if the given surface requires jpeg buffers.
+     *
+     * @param s a {@link Surface} to check.
+     * @return true if the surface requires a jpeg buffer.
+     */
+    public static boolean jpegType(Surface s) {
+        if (LegacyCameraDevice.nativeDetectSurfaceType(s) ==
+                CameraMetadataNative.NATIVE_JPEG_FORMAT) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if the given surface requires non-jpeg buffer types.
+     *
+     * <p>
+     * "Jpeg buffer" refers to the buffers returned in the jpeg
+     * {@link android.hardware.Camera.PictureCallback}.  Non-jpeg buffers are created using a tee
+     * of the preview stream drawn to the surface
+     * set via {@link android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)} or
+     * equivalent methods.
+     * </p>
+     * @param s a {@link Surface} to check.
+     * @return true if the surface requires a non-jpeg buffer type.
+     */
+    public static boolean previewType(Surface s) {
+        if (LegacyCameraDevice.nativeDetectSurfaceType(s) !=
+                CameraMetadataNative.NATIVE_JPEG_FORMAT) {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/core/java/android/hardware/camera2/legacy/RequestQueue.java b/core/java/android/hardware/camera2/legacy/RequestQueue.java
new file mode 100644
index 0000000..5c68303
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/RequestQueue.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.legacy;
+
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.utils.LongParcelable;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.ArrayDeque;
+import java.util.List;
+
+/**
+ * A queue of bursts of requests.
+ *
+ * <p>This queue maintains the count of frames that have been produced, and is thread safe.</p>
+ */
+public class RequestQueue {
+    private static final String TAG = "RequestQueue";
+
+    private static final long INVALID_FRAME = -1;
+
+    private BurstHolder mRepeatingRequest = null;
+    private final ArrayDeque<BurstHolder> mRequestQueue = new ArrayDeque<BurstHolder>();
+
+    private long mCurrentFrameNumber = 0;
+    private long mCurrentRepeatingFrameNumber = INVALID_FRAME;
+    private int mCurrentRequestId = 0;
+
+    public RequestQueue() {}
+
+    /**
+     * Return and remove the next burst on the queue.
+     *
+     * <p>If a repeating burst is returned, it will not be removed.</p>
+     *
+     * @return a pair containing the next burst and the current frame number, or null if none exist.
+     */
+    public synchronized Pair<BurstHolder, Long> getNext() {
+        BurstHolder next = mRequestQueue.poll();
+        if (next == null && mRepeatingRequest != null) {
+            next = mRepeatingRequest;
+            mCurrentRepeatingFrameNumber = mCurrentFrameNumber +
+                    next.getNumberOfRequests();
+        }
+
+        if (next == null) {
+            return null;
+        }
+
+        Pair<BurstHolder, Long> ret =  new Pair<BurstHolder, Long>(next, mCurrentFrameNumber);
+        mCurrentFrameNumber += next.getNumberOfRequests();
+        return ret;
+    }
+
+    /**
+     * Cancel a repeating request.
+     *
+     * @param requestId the id of the repeating request to cancel.
+     * @return the last frame to be returned from the HAL for the given repeating request, or
+     *          {@code INVALID_FRAME} if none exists.
+     */
+    public synchronized long stopRepeating(int requestId) {
+        long ret = INVALID_FRAME;
+        if (mRepeatingRequest != null && mRepeatingRequest.getRequestId() == requestId) {
+            mRepeatingRequest = null;
+            ret = mCurrentRepeatingFrameNumber;
+            mCurrentRepeatingFrameNumber = INVALID_FRAME;
+        } else {
+            Log.e(TAG, "cancel failed: no repeating request exists for request id: " + requestId);
+        }
+        return ret;
+    }
+
+    /**
+     * Add a the given burst to the queue.
+     *
+     * <p>If the burst is repeating, replace the current repeating burst.</p>
+     *
+     * @param requests the burst of requests to add to the queue.
+     * @param repeating true if the burst is repeating.
+     * @param frameNumber an output argument that contains either the frame number of the last frame
+     *                    that will be returned for this request, or the frame number of the last
+     *                    frame that will be returned for the current repeating request if this
+     *                    burst is set to be repeating.
+     * @return the request id.
+     */
+    public synchronized int submit(List<CaptureRequest> requests, boolean repeating,
+            /*out*/LongParcelable frameNumber) {
+        int requestId = mCurrentRequestId++;
+        BurstHolder burst = new BurstHolder(requestId, repeating, requests);
+        long ret = INVALID_FRAME;
+        if (burst.isRepeating()) {
+            if (mRepeatingRequest != null) {
+                ret = mCurrentRepeatingFrameNumber;
+            }
+            mCurrentRepeatingFrameNumber = INVALID_FRAME;
+            mRepeatingRequest = burst;
+        } else {
+            mRequestQueue.offer(burst);
+            ret = calculateLastFrame(burst.getRequestId());
+        }
+        frameNumber.setNumber(ret);
+        return requestId;
+    }
+
+    private long calculateLastFrame(int requestId) {
+        long total = mCurrentFrameNumber;
+        for (BurstHolder b : mRequestQueue) {
+            total += b.getNumberOfRequests();
+            if (b.getRequestId() == requestId) {
+                return total;
+            }
+        }
+        throw new IllegalStateException(
+                "At least one request must be in the queue to calculate frame number");
+    }
+
+}
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
new file mode 100644
index 0000000..c4669f5
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -0,0 +1,491 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.legacy;
+
+import android.graphics.ImageFormat;
+import android.graphics.SurfaceTexture;
+import android.hardware.Camera;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.os.ConditionVariable;
+import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.Pair;
+import android.view.Surface;
+
+import java.io.IOError;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * This class executes requests to the {@link Camera}.
+ *
+ * <p>
+ * The main components of this class are:
+ * - A message queue of requests to the {@link Camera}.
+ * - A thread that consumes requests to the {@link Camera} and executes them.
+ * - A {@link GLThreadManager} that draws to the configured output {@link Surface}s.
+ * - An {@link CameraDeviceState} state machine that manages the callbacks for various operations.
+ * </p>
+ */
+public class RequestThreadManager {
+    private final String TAG;
+    private final int mCameraId;
+    private final RequestHandlerThread mRequestThread;
+
+    private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG);
+    private final Camera mCamera;
+
+    private final CameraDeviceState mDeviceState;
+
+    private static final int MSG_CONFIGURE_OUTPUTS = 1;
+    private static final int MSG_SUBMIT_CAPTURE_REQUEST = 2;
+    private static final int MSG_CLEANUP = 3;
+
+    private static final int PREVIEW_FRAME_TIMEOUT = 300; // ms
+    private static final int JPEG_FRAME_TIMEOUT = 1000; // ms
+
+    private boolean mPreviewRunning = false;
+
+    private volatile RequestHolder mInFlightPreview;
+    private volatile RequestHolder mInFlightJpeg;
+
+    private List<Surface> mPreviewOutputs = new ArrayList<Surface>();
+    private List<Surface> mCallbackOutputs = new ArrayList<Surface>();
+    private GLThreadManager mGLThreadManager;
+    private SurfaceTexture mPreviewTexture;
+
+    private final RequestQueue mRequestQueue = new RequestQueue();
+    private SurfaceTexture mDummyTexture;
+    private Surface mDummySurface;
+
+    private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview");
+
+    /**
+     * Container object for Configure messages.
+     */
+    private static class ConfigureHolder {
+        public final ConditionVariable condition;
+        public final Collection<Surface> surfaces;
+
+        public ConfigureHolder(ConditionVariable condition, Collection<Surface> surfaces) {
+            this.condition = condition;
+            this.surfaces = surfaces;
+        }
+    }
+
+    /**
+     * Counter class used to calculate and log the current FPS of frame production.
+     */
+    public static class FpsCounter {
+        //TODO: Hook this up to SystTrace?
+        private static final String TAG = "FpsCounter";
+        private int mFrameCount = 0;
+        private long mLastTime = 0;
+        private long mLastPrintTime = 0;
+        private double mLastFps = 0;
+        private final String mStreamType;
+        private static final long NANO_PER_SECOND = 1000000000; //ns
+
+        public FpsCounter(String streamType) {
+            mStreamType = streamType;
+        }
+
+        public synchronized void countFrame() {
+            mFrameCount++;
+            long nextTime = SystemClock.elapsedRealtimeNanos();
+            if (mLastTime == 0) {
+                mLastTime = nextTime;
+            }
+            if (nextTime > mLastTime + NANO_PER_SECOND) {
+                long elapsed = nextTime - mLastTime;
+                mLastFps = mFrameCount * (NANO_PER_SECOND / (double) elapsed);
+                mFrameCount = 0;
+                mLastTime = nextTime;
+            }
+        }
+
+        public synchronized double checkFps() {
+            return mLastFps;
+        }
+
+        public synchronized void staggeredLog() {
+            if (mLastTime > mLastPrintTime + 5 * NANO_PER_SECOND) {
+                mLastPrintTime = mLastTime;
+                Log.d(TAG, "FPS for " + mStreamType + " stream: " + mLastFps );
+            }
+        }
+
+        public synchronized void countAndLog() {
+            countFrame();
+            staggeredLog();
+        }
+    }
+    /**
+     * Fake preview for jpeg captures when there is no active preview
+     */
+    private void createDummySurface() {
+        if (mDummyTexture == null || mDummySurface == null) {
+            mDummyTexture = new SurfaceTexture(/*ignored*/0);
+            // TODO: use smallest default sizes
+            mDummyTexture.setDefaultBufferSize(640, 480);
+            mDummySurface = new Surface(mDummyTexture);
+        }
+    }
+
+    private final ConditionVariable mReceivedJpeg = new ConditionVariable(false);
+    private final ConditionVariable mReceivedPreview = new ConditionVariable(false);
+
+    private final Camera.PictureCallback mJpegCallback = new Camera.PictureCallback() {
+        @Override
+        public void onPictureTaken(byte[] data, Camera camera) {
+            Log.i(TAG, "Received jpeg.");
+            RequestHolder holder = mInFlightJpeg;
+            if (holder == null) {
+                Log.w(TAG, "Dropping jpeg frame.");
+                mInFlightJpeg = null;
+                return;
+            }
+            for (Surface s : holder.getHolderTargets()) {
+                if (RequestHolder.jpegType(s)) {
+                    Log.i(TAG, "Producing jpeg buffer...");
+                    LegacyCameraDevice.nativeSetSurfaceDimens(s, data.length, /*height*/1);
+                    LegacyCameraDevice.nativeProduceFrame(s, data, data.length, /*height*/1,
+                            CameraMetadataNative.NATIVE_JPEG_FORMAT);
+                }
+            }
+            mReceivedJpeg.open();
+        }
+    };
+
+    private final SurfaceTexture.OnFrameAvailableListener mPreviewCallback =
+            new SurfaceTexture.OnFrameAvailableListener() {
+                @Override
+                public void onFrameAvailable(SurfaceTexture surfaceTexture) {
+                    if (DEBUG) {
+                        mPrevCounter.countAndLog();
+                    }
+                    RequestHolder holder = mInFlightPreview;
+                    if (holder == null) {
+                        Log.w(TAG, "Dropping preview frame.");
+                        mInFlightPreview = null;
+                        return;
+                    }
+                    if (holder.hasPreviewTargets()) {
+                        mGLThreadManager.queueNewFrame(holder.getHolderTargets());
+                    }
+
+                    mReceivedPreview.open();
+                }
+            };
+
+    private void stopPreview() {
+        if (mPreviewRunning) {
+            mCamera.stopPreview();
+            mPreviewRunning = false;
+        }
+    }
+
+    private void startPreview() {
+        if (!mPreviewRunning) {
+            mCamera.startPreview();
+            mPreviewRunning = true;
+        }
+    }
+
+    private void doJpegCapture(RequestHolder request) throws IOException {
+        if (!mPreviewRunning) {
+            createDummySurface();
+            mCamera.setPreviewTexture(mDummyTexture);
+            startPreview();
+        }
+        mInFlightJpeg = request;
+        // TODO: Hook up shutter callback to CameraDeviceStateListener#onCaptureStarted
+        mCamera.takePicture(/*shutter*/null, /*raw*/null, mJpegCallback);
+        mPreviewRunning = false;
+    }
+
+    private void doPreviewCapture(RequestHolder request) throws IOException {
+        mInFlightPreview = request;
+        if (mPreviewRunning) {
+            return; // Already running
+        }
+
+        mPreviewTexture.setDefaultBufferSize(640, 480); // TODO: size selection based on request
+        mCamera.setPreviewTexture(mPreviewTexture);
+        Camera.Parameters params = mCamera.getParameters();
+        List<int[]> supportedFpsRanges = params.getSupportedPreviewFpsRange();
+        int[] bestRange = getPhotoPreviewFpsRange(supportedFpsRanges);
+        if (DEBUG) {
+            Log.d(TAG, "doPreviewCapture - Selected range [" +
+                    bestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] + "," +
+                    bestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] + "]");
+        }
+        params.setPreviewFpsRange(bestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
+                bestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
+        params.setRecordingHint(true);
+        mCamera.setParameters(params);
+
+        startPreview();
+    }
+
+    private void configureOutputs(Collection<Surface> outputs) throws IOException {
+        stopPreview();
+        if (mGLThreadManager != null) {
+            mGLThreadManager.waitUntilStarted();
+            mGLThreadManager.ignoreNewFrames();
+            mGLThreadManager.waitUntilIdle();
+        }
+        mPreviewOutputs.clear();
+        mCallbackOutputs.clear();
+        mPreviewTexture = null;
+        mInFlightPreview = null;
+        mInFlightJpeg = null;
+
+        for (Surface s : outputs) {
+            int format = LegacyCameraDevice.nativeDetectSurfaceType(s);
+            switch (format) {
+                case CameraMetadataNative.NATIVE_JPEG_FORMAT:
+                    mCallbackOutputs.add(s);
+                    break;
+                default:
+                    mPreviewOutputs.add(s);
+                    break;
+            }
+        }
+
+        // TODO: Detect and optimize single-output paths here to skip stream teeing.
+        if (mGLThreadManager == null) {
+            mGLThreadManager = new GLThreadManager(mCameraId);
+            mGLThreadManager.start();
+        }
+        mGLThreadManager.waitUntilStarted();
+        mGLThreadManager.setConfigurationAndWait(mPreviewOutputs);
+        mGLThreadManager.allowNewFrames();
+        mPreviewTexture = mGLThreadManager.getCurrentSurfaceTexture();
+        mPreviewTexture.setOnFrameAvailableListener(mPreviewCallback);
+    }
+
+    // Calculate the highest FPS range supported
+    private int[] getPhotoPreviewFpsRange(List<int[]> frameRates) {
+        if (frameRates.size() == 0) {
+            Log.e(TAG, "No supported frame rates returned!");
+            return null;
+        }
+
+        int bestMin = 0;
+        int bestMax = 0;
+        int bestIndex = 0;
+        int index = 0;
+        for (int[] rate : frameRates) {
+            int minFps = rate[Camera.Parameters.PREVIEW_FPS_MIN_INDEX];
+            int maxFps = rate[Camera.Parameters.PREVIEW_FPS_MAX_INDEX];
+            if (maxFps > bestMax || (maxFps == bestMax && minFps > bestMin)) {
+                bestMin = minFps;
+                bestMax = maxFps;
+                bestIndex = index;
+            }
+            index++;
+        }
+
+        return frameRates.get(bestIndex);
+    }
+
+    private final Handler.Callback mRequestHandlerCb = new Handler.Callback() {
+        private boolean mCleanup = false;
+        private List<RequestHolder> mRepeating = null;
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public boolean handleMessage(Message msg) {
+            if (mCleanup) {
+                return true;
+            }
+
+            switch (msg.what) {
+                case MSG_CONFIGURE_OUTPUTS:
+                    ConfigureHolder config = (ConfigureHolder) msg.obj;
+                    Log.i(TAG, "Configure outputs: " + config.surfaces.size() +
+                            " surfaces configured.");
+                    try {
+                        configureOutputs(config.surfaces);
+                    } catch (IOException e) {
+                        // TODO: report error to CameraDevice
+                        throw new IOError(e);
+                    }
+                    config.condition.open();
+                    break;
+                case MSG_SUBMIT_CAPTURE_REQUEST:
+                    Handler handler = RequestThreadManager.this.mRequestThread.getHandler();
+
+                    // Get the next burst from the request queue.
+                    Pair<BurstHolder, Long> nextBurst = mRequestQueue.getNext();
+                    if (nextBurst == null) {
+                        mDeviceState.setIdle();
+                        stopPreview();
+                        break;
+                    } else {
+                        // Queue another capture if we did not get the last burst.
+                        handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST);
+                    }
+
+                    // Complete each request in the burst
+                    List<RequestHolder> requests =
+                            nextBurst.first.produceRequestHolders(nextBurst.second);
+                    for (RequestHolder holder : requests) {
+                        mDeviceState.setCaptureStart(holder);
+                        try {
+                            if (holder.hasPreviewTargets()) {
+                                mReceivedPreview.close();
+                                doPreviewCapture(holder);
+                                if (!mReceivedPreview.block(PREVIEW_FRAME_TIMEOUT)) {
+                                    // TODO: report error to CameraDevice
+                                    Log.e(TAG, "Hit timeout for preview callback!");
+                                }
+                            }
+                            if (holder.hasJpegTargets()) {
+                                mReceivedJpeg.close();
+                                doJpegCapture(holder);
+                                mReceivedJpeg.block();
+                                if (!mReceivedJpeg.block(JPEG_FRAME_TIMEOUT)) {
+                                    // TODO: report error to CameraDevice
+                                    Log.e(TAG, "Hit timeout for jpeg callback!");
+                                }
+                                mInFlightJpeg = null;
+                            }
+                        } catch (IOException e) {
+                            // TODO: err handling
+                            throw new IOError(e);
+                        }
+                        // TODO: Set fields in result.
+                        mDeviceState.setCaptureResult(holder, new CameraMetadataNative());
+                    }
+                    break;
+                case MSG_CLEANUP:
+                    mCleanup = true;
+                    if (mGLThreadManager != null) {
+                        mGLThreadManager.quit();
+                    }
+                    if (mCamera != null) {
+                        mCamera.release();
+                    }
+                    break;
+                default:
+                    throw new AssertionError("Unhandled message " + msg.what +
+                            " on RequestThread.");
+            }
+            return true;
+        }
+    };
+
+    /**
+     * Create a new RequestThreadManager.
+     *
+     * @param cameraId the id of the camera to use.
+     * @param camera an open camera object.  The RequestThreadManager takes ownership of this camera
+     *               object, and is responsible for closing it.
+     * @param deviceState a {@link CameraDeviceState} state machine.
+     */
+    public RequestThreadManager(int cameraId, Camera camera,
+                                CameraDeviceState deviceState) {
+        mCamera = camera;
+        mCameraId = cameraId;
+        String name = String.format("RequestThread-%d", cameraId);
+        TAG = name;
+        mDeviceState = deviceState;
+        mRequestThread = new RequestHandlerThread(name, mRequestHandlerCb);
+    }
+
+    /**
+     * Start the request thread.
+     */
+    public void start() {
+        mRequestThread.start();
+    }
+
+    /**
+     * Flush the pending requests.
+     */
+    public void flush() {
+        // TODO: Implement flush.
+        Log.e(TAG, "flush not yet implemented.");
+    }
+
+    /**
+     * Quit the request thread, and clean up everything.
+     */
+    public void quit() {
+        Handler handler = mRequestThread.waitAndGetHandler();
+        handler.sendMessageAtFrontOfQueue(handler.obtainMessage(MSG_CLEANUP));
+        mRequestThread.quitSafely();
+    }
+
+    /**
+     * Submit the given burst of requests to be captured.
+     *
+     * <p>If the burst is repeating, replace the current repeating burst.</p>
+     *
+     * @param requests the burst of requests to add to the queue.
+     * @param repeating true if the burst is repeating.
+     * @param frameNumber an output argument that contains either the frame number of the last frame
+     *                    that will be returned for this request, or the frame number of the last
+     *                    frame that will be returned for the current repeating request if this
+     *                    burst is set to be repeating.
+     * @return the request id.
+     */
+    public int submitCaptureRequests(List<CaptureRequest> requests, boolean repeating,
+            /*out*/LongParcelable frameNumber) {
+        Handler handler = mRequestThread.waitAndGetHandler();
+        int ret = mRequestQueue.submit(requests, repeating, frameNumber);
+        handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST);
+        return ret;
+    }
+
+    /**
+     * Cancel a repeating request.
+     *
+     * @param requestId the id of the repeating request to cancel.
+     * @return the last frame to be returned from the HAL for the given repeating request, or
+     *          {@code INVALID_FRAME} if none exists.
+     */
+    public long cancelRepeating(int requestId) {
+        return mRequestQueue.stopRepeating(requestId);
+    }
+
+
+    /**
+     * Configure with the current output Surfaces.
+     *
+     * <p>
+     * This operation blocks until the configuration is complete.
+     * </p>
+     *
+     * @param outputs a {@link java.util.Collection} of outputs to configure.
+     */
+    public void configure(Collection<Surface> outputs) {
+        Handler handler = mRequestThread.waitAndGetHandler();
+        final ConditionVariable condition = new ConditionVariable(/*closed*/false);
+        ConfigureHolder holder = new ConfigureHolder(condition, outputs);
+        handler.sendMessage(handler.obtainMessage(MSG_CONFIGURE_OUTPUTS, 0, 0, holder));
+        condition.block();
+    }
+}
diff --git a/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
new file mode 100644
index 0000000..2f0f6bc
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/SurfaceTextureRenderer.java
@@ -0,0 +1,522 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package android.hardware.camera2.legacy;
+
+import android.graphics.ImageFormat;
+import android.graphics.SurfaceTexture;
+import android.opengl.EGL14;
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLSurface;
+import android.opengl.GLES11Ext;
+import android.opengl.GLES20;
+import android.opengl.Matrix;
+import android.util.Log;
+import android.view.Surface;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * A renderer class that manages the GL state, and can draw a frame into a set of output
+ * {@link Surface}s.
+ */
+public class SurfaceTextureRenderer {
+    private static final String TAG = SurfaceTextureRenderer.class.getSimpleName();
+    private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG);
+    private static final int EGL_RECORDABLE_ANDROID = 0x3142; // from EGL/eglext.h
+    private static final int GL_MATRIX_SIZE = 16;
+    private static final int VERTEX_POS_SIZE = 3;
+    private static final int VERTEX_UV_SIZE = 2;
+    private static final int EGL_COLOR_BITLENGTH = 8;
+    private static final int GLES_VERSION = 2;
+    private static final int PBUFFER_PIXEL_BYTES = 4;
+
+    private EGLDisplay mEGLDisplay = EGL14.EGL_NO_DISPLAY;
+    private EGLContext mEGLContext = EGL14.EGL_NO_CONTEXT;
+    private EGLConfig mConfigs;
+
+    private class EGLSurfaceHolder {
+        Surface surface;
+        EGLSurface eglSurface;
+        int width;
+        int height;
+    }
+
+    private List<EGLSurfaceHolder> mSurfaces = new ArrayList<EGLSurfaceHolder>();
+    private List<EGLSurfaceHolder> mConversionSurfaces = new ArrayList<EGLSurfaceHolder>();
+
+    private ByteBuffer mPBufferPixels;
+
+    // Hold this to avoid GC
+    private volatile SurfaceTexture mSurfaceTexture;
+
+    private static final int FLOAT_SIZE_BYTES = 4;
+    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
+    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
+    private final float[] mTriangleVerticesData = {
+            // X, Y, Z, U, V
+            -1.0f, -1.0f, 0, 0.f, 0.f,
+            1.0f, -1.0f, 0, 1.f, 0.f,
+            -1.0f,  1.0f, 0, 0.f, 1.f,
+            1.0f,  1.0f, 0, 1.f, 1.f,
+    };
+
+    private FloatBuffer mTriangleVertices;
+
+    /**
+     * As used in this file, this vertex shader maps a unit square to the view, and
+     * tells the fragment shader to interpolate over it.  Each surface pixel position
+     * is mapped to a 2D homogeneous texture coordinate of the form (s, t, 0, 1) with
+     * s and t in the inclusive range [0, 1], and the matrix from
+     * {@link SurfaceTexture#getTransformMatrix(float[])} is used to map this
+     * coordinate to a texture location.
+     */
+    private static final String VERTEX_SHADER =
+            "uniform mat4 uMVPMatrix;\n" +
+                    "uniform mat4 uSTMatrix;\n" +
+                    "attribute vec4 aPosition;\n" +
+                    "attribute vec4 aTextureCoord;\n" +
+                    "varying vec2 vTextureCoord;\n" +
+                    "void main() {\n" +
+                    "  gl_Position = uMVPMatrix * aPosition;\n" +
+                    "  vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
+                    "}\n";
+
+    /**
+     * This fragment shader simply draws the color in the 2D texture at
+     * the location from the {@code VERTEX_SHADER}.
+     */
+    private static final String FRAGMENT_SHADER =
+            "#extension GL_OES_EGL_image_external : require\n" +
+                    "precision mediump float;\n" +
+                    "varying vec2 vTextureCoord;\n" +
+                    "uniform samplerExternalOES sTexture;\n" +
+                    "void main() {\n" +
+                    "  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
+                    "}\n";
+
+    private float[] mMVPMatrix = new float[GL_MATRIX_SIZE];
+    private float[] mSTMatrix = new float[GL_MATRIX_SIZE];
+
+    private int mProgram;
+    private int mTextureID = 0;
+    private int muMVPMatrixHandle;
+    private int muSTMatrixHandle;
+    private int maPositionHandle;
+    private int maTextureHandle;
+
+    public SurfaceTextureRenderer() {
+        mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length *
+                FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
+        mTriangleVertices.put(mTriangleVerticesData).position(0);
+        Matrix.setIdentityM(mSTMatrix, 0);
+    }
+
+    private int loadShader(int shaderType, String source) {
+        int shader = GLES20.glCreateShader(shaderType);
+        checkGlError("glCreateShader type=" + shaderType);
+        GLES20.glShaderSource(shader, source);
+        GLES20.glCompileShader(shader);
+        int[] compiled = new int[1];
+        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
+        if (compiled[0] == 0) {
+            Log.e(TAG, "Could not compile shader " + shaderType + ":");
+            Log.e(TAG, " " + GLES20.glGetShaderInfoLog(shader));
+            GLES20.glDeleteShader(shader);
+            // TODO: handle this more gracefully
+            throw new IllegalStateException("Could not compile shader " + shaderType);
+        }
+        return shader;
+    }
+
+    private int createProgram(String vertexSource, String fragmentSource) {
+        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
+        if (vertexShader == 0) {
+            return 0;
+        }
+        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
+        if (pixelShader == 0) {
+            return 0;
+        }
+
+        int program = GLES20.glCreateProgram();
+        checkGlError("glCreateProgram");
+        if (program == 0) {
+            Log.e(TAG, "Could not create program");
+        }
+        GLES20.glAttachShader(program, vertexShader);
+        checkGlError("glAttachShader");
+        GLES20.glAttachShader(program, pixelShader);
+        checkGlError("glAttachShader");
+        GLES20.glLinkProgram(program);
+        int[] linkStatus = new int[1];
+        GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
+        if (linkStatus[0] != GLES20.GL_TRUE) {
+            Log.e(TAG, "Could not link program: ");
+            Log.e(TAG, GLES20.glGetProgramInfoLog(program));
+            GLES20.glDeleteProgram(program);
+            // TODO: handle this more gracefully
+            throw new IllegalStateException("Could not link program");
+        }
+        return program;
+    }
+
+    private void drawFrame(SurfaceTexture st) {
+        checkGlError("onDrawFrame start");
+        st.getTransformMatrix(mSTMatrix);
+
+        if (DEBUG) {
+            GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+            GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+        }
+
+        GLES20.glUseProgram(mProgram);
+        checkGlError("glUseProgram");
+
+        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
+        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
+
+        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
+        GLES20.glVertexAttribPointer(maPositionHandle, VERTEX_POS_SIZE, GLES20.GL_FLOAT,
+                /*normalized*/ false,TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+        checkGlError("glVertexAttribPointer maPosition");
+        GLES20.glEnableVertexAttribArray(maPositionHandle);
+        checkGlError("glEnableVertexAttribArray maPositionHandle");
+
+        mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
+        GLES20.glVertexAttribPointer(maTextureHandle, VERTEX_UV_SIZE, GLES20.GL_FLOAT,
+                /*normalized*/ false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
+        checkGlError("glVertexAttribPointer maTextureHandle");
+        GLES20.glEnableVertexAttribArray(maTextureHandle);
+        checkGlError("glEnableVertexAttribArray maTextureHandle");
+
+        Matrix.setIdentityM(mMVPMatrix, 0);
+        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, /*count*/ 1, /*transpose*/ false, mMVPMatrix,
+                /*offset*/ 0);
+        GLES20.glUniformMatrix4fv(muSTMatrixHandle, /*count*/ 1, /*transpose*/ false, mSTMatrix,
+                /*offset*/ 0);
+
+        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, /*offset*/ 0, /*count*/ 4);
+        checkGlError("glDrawArrays");
+        GLES20.glFinish();
+    }
+
+    /**
+     * Initializes GL state.  Call this after the EGL surface has been created and made current.
+     */
+    private void initializeGLState() {
+        mProgram = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
+        if (mProgram == 0) {
+            throw new IllegalStateException("failed creating program");
+        }
+        maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
+        checkGlError("glGetAttribLocation aPosition");
+        if (maPositionHandle == -1) {
+            throw new IllegalStateException("Could not get attrib location for aPosition");
+        }
+        maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
+        checkGlError("glGetAttribLocation aTextureCoord");
+        if (maTextureHandle == -1) {
+            throw new IllegalStateException("Could not get attrib location for aTextureCoord");
+        }
+
+        muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
+        checkGlError("glGetUniformLocation uMVPMatrix");
+        if (muMVPMatrixHandle == -1) {
+            throw new IllegalStateException("Could not get attrib location for uMVPMatrix");
+        }
+
+        muSTMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uSTMatrix");
+        checkGlError("glGetUniformLocation uSTMatrix");
+        if (muSTMatrixHandle == -1) {
+            throw new IllegalStateException("Could not get attrib location for uSTMatrix");
+        }
+
+        int[] textures = new int[1];
+        GLES20.glGenTextures(/*n*/ 1, textures, /*offset*/ 0);
+
+        mTextureID = textures[0];
+        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);
+        checkGlError("glBindTexture mTextureID");
+
+        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER,
+                GLES20.GL_NEAREST);
+        GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER,
+                GLES20.GL_LINEAR);
+        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S,
+                GLES20.GL_CLAMP_TO_EDGE);
+        GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T,
+                GLES20.GL_CLAMP_TO_EDGE);
+        checkGlError("glTexParameter");
+    }
+
+    private int getTextureId() {
+        return mTextureID;
+    }
+
+    private void clearState() {
+        mSurfaces.clear();
+        mConversionSurfaces.clear();
+        mPBufferPixels = null;
+        mSurfaceTexture = null;
+    }
+
+    private void configureEGLContext() {
+        mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
+        if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
+            throw new IllegalStateException("No EGL14 display");
+        }
+        int[] version = new int[2];
+        if (!EGL14.eglInitialize(mEGLDisplay, version, /*offset*/ 0, version, /*offset*/ 1)) {
+            throw new IllegalStateException("Cannot initialize EGL14");
+        }
+
+        int[] attribList = {
+                EGL14.EGL_RED_SIZE, EGL_COLOR_BITLENGTH,
+                EGL14.EGL_GREEN_SIZE, EGL_COLOR_BITLENGTH,
+                EGL14.EGL_BLUE_SIZE, EGL_COLOR_BITLENGTH,
+                EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
+                EGL_RECORDABLE_ANDROID, 1,
+                EGL14.EGL_SURFACE_TYPE, EGL14.EGL_PBUFFER_BIT | EGL14.EGL_WINDOW_BIT,
+                EGL14.EGL_NONE
+        };
+        EGLConfig[] configs = new EGLConfig[1];
+        int[] numConfigs = new int[1];
+        EGL14.eglChooseConfig(mEGLDisplay, attribList, /*offset*/ 0, configs, /*offset*/ 0,
+                configs.length, numConfigs, /*offset*/ 0);
+        checkEglError("eglCreateContext RGB888+recordable ES2");
+        mConfigs = configs[0];
+        int[] attrib_list = {
+                EGL14.EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION,
+                EGL14.EGL_NONE
+        };
+        mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
+                attrib_list, /*offset*/ 0);
+        checkEglError("eglCreateContext");
+        if(mEGLContext == EGL14.EGL_NO_CONTEXT) {
+            throw new IllegalStateException("No EGLContext could be made");
+        }
+    }
+
+    private void configureEGLOutputSurfaces(Collection<EGLSurfaceHolder> surfaces) {
+        if (surfaces == null || surfaces.size() == 0) {
+            throw new IllegalStateException("No Surfaces were provided to draw to");
+        }
+        int[] surfaceAttribs = {
+                EGL14.EGL_NONE
+        };
+        for (EGLSurfaceHolder holder : surfaces) {
+            holder.eglSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, mConfigs, holder.surface,
+                    surfaceAttribs, 0);
+            checkEglError("eglCreateWindowSurface");
+        }
+    }
+
+    private void configureEGLPbufferSurfaces(Collection<EGLSurfaceHolder> surfaces) {
+        if (surfaces == null || surfaces.size() == 0) {
+            throw new IllegalStateException("No Surfaces were provided to draw to");
+        }
+
+        int maxLength = 0;
+        int[] dimens = new int[2];
+        for (EGLSurfaceHolder holder : surfaces) {
+            LegacyCameraDevice.nativeDetectSurfaceDimens(holder.surface, dimens);
+            int length = dimens[0] * dimens[1];
+            // Find max surface size, ensure PBuffer can hold this many pixels
+            maxLength = (length > maxLength) ? length : maxLength;
+            int[] surfaceAttribs = {
+                    EGL14.EGL_WIDTH, dimens[0],
+                    EGL14.EGL_HEIGHT, dimens[1],
+                    EGL14.EGL_NONE
+            };
+            holder.width = dimens[0];
+            holder.height = dimens[1];
+            holder.eglSurface =
+                    EGL14.eglCreatePbufferSurface(mEGLDisplay, mConfigs, surfaceAttribs, 0);
+            checkEglError("eglCreatePbufferSurface");
+        }
+        mPBufferPixels = ByteBuffer.allocateDirect(maxLength * PBUFFER_PIXEL_BYTES)
+                .order(ByteOrder.nativeOrder());
+    }
+
+    private void releaseEGLContext() {
+        if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
+            EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE,
+                    EGL14.EGL_NO_CONTEXT);
+            if (mSurfaces != null) {
+                for (EGLSurfaceHolder holder : mSurfaces) {
+                    if (holder.eglSurface != null) {
+                        EGL14.eglDestroySurface(mEGLDisplay, holder.eglSurface);
+                    }
+                }
+            }
+            if (mConversionSurfaces != null) {
+                for (EGLSurfaceHolder holder : mConversionSurfaces) {
+                    if (holder.eglSurface != null) {
+                        EGL14.eglDestroySurface(mEGLDisplay, holder.eglSurface);
+                    }
+                }
+            }
+            EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
+            EGL14.eglReleaseThread();
+            EGL14.eglTerminate(mEGLDisplay);
+        }
+
+        mConfigs = null;
+        mEGLDisplay = EGL14.EGL_NO_DISPLAY;
+        mEGLContext = EGL14.EGL_NO_CONTEXT;
+        clearState();
+    }
+
+    private void makeCurrent(EGLSurface surface) {
+        EGL14.eglMakeCurrent(mEGLDisplay, surface, surface, mEGLContext);
+        checkEglError("makeCurrent");
+    }
+
+    private boolean swapBuffers(EGLSurface surface) {
+        boolean result = EGL14.eglSwapBuffers(mEGLDisplay, surface);
+        checkEglError("swapBuffers");
+        return result;
+    }
+
+    private void checkEglError(String msg) {
+        int error;
+        if ((error = EGL14.eglGetError()) != EGL14.EGL_SUCCESS) {
+            throw new IllegalStateException(msg + ": EGL error: 0x" + Integer.toHexString(error));
+        }
+    }
+
+    private void checkGlError(String msg) {
+        int error;
+        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
+            throw new IllegalStateException(msg + ": GLES20 error: 0x" + Integer.toHexString(error));
+        }
+    }
+
+    /**
+     * Return the surface texture to draw to - this is the texture use to when producing output
+     * surface buffers.
+     *
+     * @return a {@link SurfaceTexture}.
+     */
+    public SurfaceTexture getSurfaceTexture() {
+        return mSurfaceTexture;
+    }
+
+    /**
+     * Set a collection of output {@link Surface}s that can be drawn to.
+     *
+     * @param surfaces a {@link Collection} of surfaces.
+     */
+    public void configureSurfaces(Collection<Surface> surfaces) {
+        releaseEGLContext();
+
+        for (Surface s : surfaces) {
+            // If pixel conversions aren't handled by egl, use a pbuffer
+            if (LegacyCameraDevice.needsConversion(s)) {
+                LegacyCameraDevice.nativeSetSurfaceFormat(s, ImageFormat.NV21);
+                EGLSurfaceHolder holder = new EGLSurfaceHolder();
+                holder.surface = s;
+                mConversionSurfaces.add(holder);
+            } else {
+                EGLSurfaceHolder holder = new EGLSurfaceHolder();
+                holder.surface = s;
+                mSurfaces.add(holder);
+            }
+        }
+
+        // Set up egl display
+        configureEGLContext();
+
+        // Set up regular egl surfaces if needed
+        if (mSurfaces.size() > 0) {
+            configureEGLOutputSurfaces(mSurfaces);
+        }
+
+        // Set up pbuffer surface if needed
+        if (mConversionSurfaces.size() > 0) {
+            configureEGLPbufferSurfaces(mConversionSurfaces);
+        }
+        makeCurrent((mSurfaces.size() > 0) ? mSurfaces.get(0).eglSurface :
+                mConversionSurfaces.get(0).eglSurface);
+        initializeGLState();
+        mSurfaceTexture = new SurfaceTexture(getTextureId());
+    }
+
+    /**
+     * Draw the current buffer in the {@link SurfaceTexture} returned from
+     * {@link #getSurfaceTexture()} into the given set of target surfaces.
+     *
+     * <p>
+     * The given surfaces must be a subset of the surfaces set in the last
+     * {@link #configureSurfaces(java.util.Collection)} call.
+     * </p>
+     *
+     * @param targetSurfaces the surfaces to draw to.
+     */
+    public void drawIntoSurfaces(Collection<Surface> targetSurfaces) {
+        if ((mSurfaces == null || mSurfaces.size() == 0)
+                && (mConversionSurfaces == null || mConversionSurfaces.size() == 0)) {
+            return;
+        }
+        checkGlError("before updateTexImage");
+        mSurfaceTexture.updateTexImage();
+        for (EGLSurfaceHolder holder : mSurfaces) {
+            if (targetSurfaces.contains(holder.surface)) {
+                makeCurrent(holder.eglSurface);
+                drawFrame(mSurfaceTexture);
+                swapBuffers(holder.eglSurface);
+            }
+
+        }
+        for (EGLSurfaceHolder holder : mConversionSurfaces) {
+            if (targetSurfaces.contains(holder.surface)) {
+                makeCurrent(holder.eglSurface);
+                drawFrame(mSurfaceTexture);
+                mPBufferPixels.clear();
+                GLES20.glReadPixels(/*x*/ 0, /*y*/ 0, holder.width, holder.height, GLES20.GL_RGBA,
+                        GLES20.GL_UNSIGNED_BYTE, mPBufferPixels);
+                checkGlError("glReadPixels");
+                int format = LegacyCameraDevice.nativeDetectSurfaceType(holder.surface);
+                LegacyCameraDevice.nativeProduceFrame(holder.surface, mPBufferPixels.array(),
+                        holder.width, holder.height, format);
+                swapBuffers(holder.eglSurface);
+            }
+        }
+    }
+
+    /**
+     * Clean up the current GL context.
+     */
+    public void cleanupEGLContext() {
+        releaseEGLContext();
+    }
+
+    /**
+     * Drop all current GL operations on the floor.
+     */
+    public void flush() {
+        // TODO: implement flush
+        Log.e(TAG, "Flush not yet implemented.");
+    }
+}
diff --git a/core/java/android/hardware/camera2/legacy/package.html b/core/java/android/hardware/camera2/legacy/package.html
new file mode 100644
index 0000000..db6f78b
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body>
\ No newline at end of file
diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
index 328ccbe..40cda08 100644
--- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
+++ b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
@@ -40,6 +40,7 @@
     public static final int ALREADY_EXISTS = -17;
     public static final int BAD_VALUE = -22;
     public static final int DEAD_OBJECT = -32;
+    public static final int INVALID_OPERATION = -38;
 
     /**
      * TODO: add as error codes in Errors.h
@@ -53,6 +54,7 @@
     public static final int EOPNOTSUPP = -95;
     public static final int EUSERS = -87;
 
+
     private static class CameraBinderDecoratorListener implements Decorator.DecoratorListener {
 
         @Override
@@ -125,6 +127,9 @@
             case EOPNOTSUPP:
                 UncheckedThrow.throwAnyException(new CameraRuntimeException(
                         CAMERA_DEPRECATED_HAL));
+            case INVALID_OPERATION:
+                UncheckedThrow.throwAnyException(new IllegalStateException(
+                        "Illegal state encountered in camera service."));
         }
 
         /**
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index f3de547..5b6e862 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -114,10 +114,10 @@
      * Adds a listener to get informed of {@link HdmiHotplugEvent}.
      *
      * <p>To stop getting the notification,
-     * use {@link #removeHotplugeEventListener(HotplugEventListener)}.
+     * use {@link #removeHotplugEventListener(HotplugEventListener)}.
      *
      * @param listener {@link HotplugEventListener} instance
-     * @see HdmiControlManager#removeHotplugeEventListener(HotplugEventListener)
+     * @see HdmiControlManager#removeHotplugEventListener(HotplugEventListener)
      */
     public void addHotplugEventListener(HotplugEventListener listener) {
         if (mService == null) {
@@ -135,7 +135,7 @@
      *
      * @param listener {@link HotplugEventListener} instance to be removed
      */
-    public void removeHotplugeEventListener(HotplugEventListener listener) {
+    public void removeHotplugEventListener(HotplugEventListener listener) {
         if (mService == null) {
             return;
         }
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
new file mode 100644
index 0000000..70cc708
--- /dev/null
+++ b/core/java/android/net/EthernetManager.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.content.Context;
+import android.net.IEthernetManager;
+import android.net.IpConfiguration;
+import android.net.IpConfiguration.IpAssignment;
+import android.net.IpConfiguration.ProxySettings;
+import android.net.LinkProperties;
+import android.os.RemoteException;
+
+/**
+ * A class representing the IP configuration of the Ethernet network.
+ *
+ * @hide
+ */
+public class EthernetManager {
+    private static final String TAG = "EthernetManager";
+
+    private final Context mContext;
+    private final IEthernetManager mService;
+
+    /**
+     * Create a new EthernetManager instance.
+     * Applications will almost always want to use
+     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
+     * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
+     */
+    public EthernetManager(Context context, IEthernetManager service) {
+        mContext = context;
+        mService = service;
+    }
+
+    /**
+     * Get Ethernet configuration
+     * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
+     */
+    public IpConfiguration getConfiguration() {
+        try {
+            return mService.getConfiguration();
+        } catch (RemoteException e) {
+            return new IpConfiguration(IpAssignment.UNASSIGNED,
+                                       ProxySettings.UNASSIGNED,
+                                       new LinkProperties());
+        }
+    }
+
+    /**
+     * Set Ethernet configuration
+     * @return true if setting success
+     */
+    public void setConfiguration(IpConfiguration config) {
+        try {
+            mService.setConfiguration(config);
+        } catch (RemoteException e) {
+        }
+    }
+}
diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl
new file mode 100644
index 0000000..3fa08f8
--- /dev/null
+++ b/core/java/android/net/IEthernetManager.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.IpConfiguration;
+
+/**
+ * Interface that answers queries about, and allows changing
+ * ethernet configuration.
+ */
+/** {@hide} */
+interface IEthernetManager
+{
+    IpConfiguration getConfiguration();
+    void setConfiguration(in IpConfiguration config);
+}
diff --git a/core/java/android/os/BatteryProperty.java b/core/java/android/os/BatteryProperty.java
index 0ed856e..27dad4f 100644
--- a/core/java/android/os/BatteryProperty.java
+++ b/core/java/android/os/BatteryProperty.java
@@ -56,7 +56,7 @@
     /**
      * Battery remaining energy in nanowatt-hours, as a long integer.
      */
-    public static final int ENERGY_COUNTER = 4;
+    public static final int ENERGY_COUNTER = 5;
 
     private long mValueLong;
 
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index b907375..6b8e2de 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -287,6 +287,16 @@
         public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 1 << 5;
 
         /**
+         * Flag indicating that a document can be renamed.
+         *
+         * @see #COLUMN_FLAGS
+         * @see DocumentsContract#renameDocument(ContentProviderClient, Uri,
+         *      String)
+         * @see DocumentsProvider#renameDocument(String, String)
+         */
+        public static final int FLAG_SUPPORTS_RENAME = 1 << 6;
+
+        /**
          * Flag indicating that document titles should be hidden when viewing
          * this directory in a larger format grid. For example, a directory
          * containing only images may want the image thumbnails to speak for
@@ -494,6 +504,8 @@
     /** {@hide} */
     public static final String METHOD_CREATE_DOCUMENT = "android:createDocument";
     /** {@hide} */
+    public static final String METHOD_RENAME_DOCUMENT = "android:renameDocument";
+    /** {@hide} */
     public static final String METHOD_DELETE_DOCUMENT = "android:deleteDocument";
 
     /** {@hide} */
@@ -898,6 +910,45 @@
     }
 
     /**
+     * Change the display name of an existing document.
+     * <p>
+     * If the underlying provider needs to create a new
+     * {@link Document#COLUMN_DOCUMENT_ID} to represent the updated display
+     * name, that new document is returned and the original document is no
+     * longer valid. Otherwise, the original document is returned.
+     *
+     * @param documentUri document with {@link Document#FLAG_SUPPORTS_RENAME}
+     * @param displayName updated name for document
+     * @return the existing or new document after the rename, or {@code null} if
+     *         failed.
+     */
+    public static Uri renameDocument(ContentResolver resolver, Uri documentUri,
+            String displayName) {
+        final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
+                documentUri.getAuthority());
+        try {
+            return renameDocument(client, documentUri, displayName);
+        } catch (Exception e) {
+            Log.w(TAG, "Failed to rename document", e);
+            return null;
+        } finally {
+            ContentProviderClient.releaseQuietly(client);
+        }
+    }
+
+    /** {@hide} */
+    public static Uri renameDocument(ContentProviderClient client, Uri documentUri,
+            String displayName) throws RemoteException {
+        final Bundle in = new Bundle();
+        in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
+        in.putString(Document.COLUMN_DISPLAY_NAME, displayName);
+
+        final Bundle out = client.call(METHOD_RENAME_DOCUMENT, null, in);
+        final Uri outUri = out.getParcelable(DocumentsContract.EXTRA_URI);
+        return (outUri != null) ? outUri : documentUri;
+    }
+
+    /**
      * Delete the given document.
      *
      * @param documentUri document with {@link Document#FLAG_SUPPORTS_DELETE}
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 1a7a00f2..066b4aa 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -19,9 +19,11 @@
 import static android.provider.DocumentsContract.EXTRA_THUMBNAIL_SIZE;
 import static android.provider.DocumentsContract.METHOD_CREATE_DOCUMENT;
 import static android.provider.DocumentsContract.METHOD_DELETE_DOCUMENT;
+import static android.provider.DocumentsContract.METHOD_RENAME_DOCUMENT;
 import static android.provider.DocumentsContract.getDocumentId;
 import static android.provider.DocumentsContract.getRootId;
 import static android.provider.DocumentsContract.getSearchDocumentsQuery;
+import static android.provider.DocumentsContract.isViaUri;
 
 import android.content.ContentProvider;
 import android.content.ContentResolver;
@@ -206,7 +208,7 @@
      *            If the MIME type is not supported, the provider must throw.
      * @param displayName the display name of the new document. The provider may
      *            alter this name to meet any internal constraints, such as
-     *            conflicting names.
+     *            avoiding conflicting names.
      */
     @SuppressWarnings("unused")
     public String createDocument(String parentDocumentId, String mimeType, String displayName)
@@ -215,11 +217,33 @@
     }
 
     /**
-     * Delete the requested document. Upon returning, any URI permission grants
-     * for the given document will be revoked. If additional documents were
-     * deleted as a side effect of this call (such as documents inside a
-     * directory) the implementor is responsible for revoking those permissions
-     * using {@link #revokeDocumentPermission(String)}.
+     * Rename an existing document.
+     * <p>
+     * If a different {@link Document#COLUMN_DOCUMENT_ID} must be used to
+     * represent the renamed document, generate and return it. Any outstanding
+     * URI permission grants will be updated to point at the new document. If
+     * the original {@link Document#COLUMN_DOCUMENT_ID} is still valid after the
+     * rename, return {@code null}.
+     *
+     * @param documentId the document to rename.
+     * @param displayName the updated display name of the document. The provider
+     *            may alter this name to meet any internal constraints, such as
+     *            avoiding conflicting names.
+     */
+    @SuppressWarnings("unused")
+    public String renameDocument(String documentId, String displayName)
+            throws FileNotFoundException {
+        throw new UnsupportedOperationException("Rename not supported");
+    }
+
+    /**
+     * Delete the requested document.
+     * <p>
+     * Upon returning, any URI permission grants for the given document will be
+     * revoked. If additional documents were deleted as a side effect of this
+     * call (such as documents inside a directory) the implementor is
+     * responsible for revoking those permissions using
+     * {@link #revokeDocumentPermission(String)}.
      *
      * @param documentId the document to delete.
      */
@@ -523,26 +547,33 @@
                         DocumentsContract.getDocumentId(uri));
 
                 // Caller may only have prefix grant, so extend them a grant to
-                // the narrow Uri. Caller already holds read grant to get here,
-                // so check for any other modes we should extend.
-                int modeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
-                if (context.checkCallingOrSelfUriPermission(uri,
-                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
-                        == PackageManager.PERMISSION_GRANTED) {
-                    modeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
-                }
-                if (context.checkCallingOrSelfUriPermission(uri,
-                        Intent.FLAG_GRANT_READ_URI_PERMISSION
-                        | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
-                        == PackageManager.PERMISSION_GRANTED) {
-                    modeFlags |= Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
-                }
+                // the narrow URI.
+                final int modeFlags = getCallingOrSelfUriPermissionModeFlags(context, uri);
                 context.grantUriPermission(getCallingPackage(), narrowUri, modeFlags);
                 return narrowUri;
         }
         return null;
     }
 
+    private static int getCallingOrSelfUriPermissionModeFlags(Context context, Uri uri) {
+        // TODO: move this to a direct AMS call
+        int modeFlags = 0;
+        if (context.checkCallingOrSelfUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
+                == PackageManager.PERMISSION_GRANTED) {
+            modeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION;
+        }
+        if (context.checkCallingOrSelfUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+                == PackageManager.PERMISSION_GRANTED) {
+            modeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+        }
+        if (context.checkCallingOrSelfUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
+                == PackageManager.PERMISSION_GRANTED) {
+            modeFlags |= Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
+        }
+        return modeFlags;
+    }
+
     /**
      * Implementation is provided by the parent class. Throws by default, and
      * cannot be overriden.
@@ -588,6 +619,7 @@
             return super.call(method, arg, extras);
         }
 
+        final Context context = getContext();
         final Uri documentUri = extras.getParcelable(DocumentsContract.EXTRA_URI);
         final String authority = documentUri.getAuthority();
         final String documentId = DocumentsContract.getDocumentId(documentUri);
@@ -605,7 +637,6 @@
 
                 final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
                 final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
-
                 final String newDocumentId = createDocument(documentId, mimeType, displayName);
 
                 // No need to issue new grants here, since caller either has
@@ -615,6 +646,30 @@
                         newDocumentId);
                 out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
 
+            } else if (METHOD_RENAME_DOCUMENT.equals(method)) {
+                enforceWritePermissionInner(documentUri);
+
+                final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
+                final String newDocumentId = renameDocument(documentId, displayName);
+
+                if (newDocumentId != null) {
+                    final Uri newDocumentUri = DocumentsContract.buildDocumentMaybeViaUri(
+                            documentUri, newDocumentId);
+
+                    // If caller came in with a narrow grant, issue them a
+                    // narrow grant for the newly renamed document.
+                    if (!isViaUri(newDocumentUri)) {
+                        final int modeFlags = getCallingOrSelfUriPermissionModeFlags(context,
+                                documentUri);
+                        context.grantUriPermission(getCallingPackage(), newDocumentUri, modeFlags);
+                    }
+
+                    out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
+
+                    // Original document no longer exists, clean up any grants
+                    revokeDocumentPermission(documentId);
+                }
+
             } else if (METHOD_DELETE_DOCUMENT.equals(method)) {
                 enforceWritePermissionInner(documentUri);
                 deleteDocument(documentId);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 355204e..835a648 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -36,6 +36,8 @@
 	android_opengl_GLES11Ext.cpp \
 	android_opengl_GLES20.cpp \
 	android_opengl_GLES30.cpp \
+	android_opengl_GLES31.cpp \
+	android_opengl_GLES31Ext.cpp \
 	android_database_CursorWindow.cpp \
 	android_database_SQLiteCommon.cpp \
 	android_database_SQLiteConnection.cpp \
@@ -135,6 +137,7 @@
 	android_media_ToneGenerator.cpp \
 	android_hardware_Camera.cpp \
 	android_hardware_camera2_CameraMetadata.cpp \
+	android_hardware_camera2_legacy_LegacyCameraDevice.cpp \
 	android_hardware_SensorManager.cpp \
 	android_hardware_SerialPort.cpp \
 	android_hardware_UsbDevice.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index a4dc824..2d350e0 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -74,9 +74,12 @@
 extern int register_android_opengl_jni_GLES11Ext(JNIEnv* env);
 extern int register_android_opengl_jni_GLES20(JNIEnv* env);
 extern int register_android_opengl_jni_GLES30(JNIEnv* env);
+extern int register_android_opengl_jni_GLES31(JNIEnv* env);
+extern int register_android_opengl_jni_GLES31Ext(JNIEnv* env);
 
 extern int register_android_hardware_Camera(JNIEnv *env);
 extern int register_android_hardware_camera2_CameraMetadata(JNIEnv *env);
+extern int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv *env);
 extern int register_android_hardware_SensorManager(JNIEnv *env);
 extern int register_android_hardware_SerialPort(JNIEnv *env);
 extern int register_android_hardware_UsbDevice(JNIEnv *env);
@@ -1228,6 +1231,8 @@
     REG_JNI(register_android_opengl_jni_GLES11Ext),
     REG_JNI(register_android_opengl_jni_GLES20),
     REG_JNI(register_android_opengl_jni_GLES30),
+    REG_JNI(register_android_opengl_jni_GLES31),
+    REG_JNI(register_android_opengl_jni_GLES31Ext),
 
     REG_JNI(register_android_graphics_Bitmap),
     REG_JNI(register_android_graphics_BitmapFactory),
@@ -1280,6 +1285,7 @@
     REG_JNI(register_com_android_internal_util_VirtualRefBasePtr),
     REG_JNI(register_android_hardware_Camera),
     REG_JNI(register_android_hardware_camera2_CameraMetadata),
+    REG_JNI(register_android_hardware_camera2_legacy_LegacyCameraDevice),
     REG_JNI(register_android_hardware_SensorManager),
     REG_JNI(register_android_hardware_SerialPort),
     REG_JNI(register_android_hardware_UsbDevice),
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 307293f..3a53331 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -27,6 +27,7 @@
 
 #include <cutils/properties.h>
 #include <utils/Vector.h>
+#include <utils/Errors.h>
 
 #include <gui/GLConsumer.h>
 #include <gui/Surface.h>
@@ -464,7 +465,7 @@
 }
 
 // connect to camera service
-static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
+static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
     jobject weak_this, jint cameraId, jstring clientPackageName)
 {
     // Convert jstring to String16
@@ -477,20 +478,19 @@
             Camera::USE_CALLING_UID);
 
     if (camera == NULL) {
-        jniThrowRuntimeException(env, "Fail to connect to camera service");
-        return;
+        return -EACCES;
     }
 
     // make sure camera hardware is alive
     if (camera->getStatus() != NO_ERROR) {
-        jniThrowRuntimeException(env, "Camera initialization failed");
-        return;
+        return NO_INIT;
     }
 
     jclass clazz = env->GetObjectClass(thiz);
     if (clazz == NULL) {
+        // This should never happen
         jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
-        return;
+        return INVALID_OPERATION;
     }
 
     // We use a weak reference so the Camera object can be garbage collected.
@@ -501,6 +501,7 @@
 
     // save context in opaque field
     env->SetLongField(thiz, fields.context, (jlong)context.get());
+    return NO_ERROR;
 }
 
 // disconnect from camera service
@@ -538,9 +539,9 @@
     }
 }
 
-static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, jobject jSurface)
+static void android_hardware_Camera_setPreviewSurface(JNIEnv *env, jobject thiz, jobject jSurface)
 {
-    ALOGV("setPreviewDisplay");
+    ALOGV("setPreviewSurface");
     sp<Camera> camera = get_native_camera(env, thiz, NULL);
     if (camera == 0) return;
 
@@ -890,14 +891,14 @@
     "(ILandroid/hardware/Camera$CameraInfo;)V",
     (void*)android_hardware_Camera_getCameraInfo },
   { "native_setup",
-    "(Ljava/lang/Object;ILjava/lang/String;)V",
+    "(Ljava/lang/Object;ILjava/lang/String;)I",
     (void*)android_hardware_Camera_native_setup },
   { "native_release",
     "()V",
     (void*)android_hardware_Camera_release },
-  { "setPreviewDisplay",
+  { "setPreviewSurface",
     "(Landroid/view/Surface;)V",
-    (void *)android_hardware_Camera_setPreviewDisplay },
+    (void *)android_hardware_Camera_setPreviewSurface },
   { "setPreviewTexture",
     "(Landroid/graphics/SurfaceTexture;)V",
     (void *)android_hardware_Camera_setPreviewTexture },
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 3312109..0d2df80 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -518,7 +518,7 @@
     SortedVector<String8> vendorSections;
     size_t vendorSectionCount = 0;
 
-    if (vTags != 0) {
+    if (vTags != NULL) {
         vendorSections = vTags->getAllSectionNames();
         vendorSectionCount = vendorSections.size();
     }
@@ -592,7 +592,7 @@
                                  "Could not find tag name for key '%s')", key);
             return 0;
         }
-    } else if (vTags != 0) {
+    } else if (vTags != NULL) {
         // Match vendor tags (typically com.*)
         const String8 sectionName(section);
         const String8 tagName(keyTagName);
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
new file mode 100644
index 0000000..40e9544
--- /dev/null
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Legacy-CameraDevice-JNI"
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <utils/Trace.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/android_view_Surface.h"
+
+#include <ui/GraphicBuffer.h>
+#include <system/window.h>
+
+using namespace android;
+
+// fully-qualified class name
+#define CAMERA_DEVICE_CLASS_NAME "android/hardware/camera2/legacy/LegacyCameraDevice"
+#define CAMERA_DEVICE_BUFFER_SLACK  3
+
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
+
+/**
+ * Convert from RGB 888 to Y'CbCr using the conversion specified in ITU-R BT.601 for
+ * digital RGB with K_b = 0.114, and K_r = 0.299.
+ */
+static void rgbToYuv420(uint8_t* rgbBuf, int32_t width, int32_t height, uint8_t* yPlane,
+        uint8_t* uPlane, uint8_t* vPlane, size_t chromaStep, size_t yStride, size_t chromaStride) {
+    uint8_t R, G, B;
+    size_t index = 0;
+
+    int32_t cStrideDiff = chromaStride - width;
+
+    for (int32_t j = 0; j < height; j++) {
+        for (int32_t i = 0; i < width; i++) {
+            R = rgbBuf[index++];
+            G = rgbBuf[index++];
+            B = rgbBuf[index++];
+            *(yPlane + i) = ((66 * R + 129 * G +  25 * B + 128) >> 8) +  16;
+
+            if (j % 2 == 0 && i % 2 == 0){
+                *uPlane = (( -38 * R -  74 * G + 112 * B + 128) >> 8) + 128;
+                *vPlane = (( 112 * R -  94 * G -  18 * B + 128) >> 8) + 128;
+                uPlane += chromaStep;
+                vPlane += chromaStep;
+            }
+            // Skip alpha
+            index++;
+        }
+        yPlane += yStride;
+        if (j % 2 == 0) {
+            uPlane += cStrideDiff;
+            vPlane += cStrideDiff;
+        }
+    }
+}
+
+static void rgbToYuv420(uint8_t* rgbBuf, int32_t width, int32_t height, android_ycbcr* ycbcr) {
+    size_t cStep = ycbcr->chroma_step;
+    size_t cStride = ycbcr->cstride;
+    size_t yStride = ycbcr->ystride;
+    rgbToYuv420(rgbBuf, width, height, reinterpret_cast<uint8_t*>(ycbcr->y),
+            reinterpret_cast<uint8_t*>(ycbcr->cb), reinterpret_cast<uint8_t*>(ycbcr->cr),
+            cStep, yStride, cStride);
+}
+
+static status_t configureSurface(const sp<ANativeWindow>& anw,
+                                 int32_t width,
+                                 int32_t height,
+                                 int32_t pixelFmt,
+                                 int32_t maxBufferSlack) {
+    status_t err = NO_ERROR;
+    err = native_window_set_buffers_dimensions(anw.get(), width, height);
+    if (err != NO_ERROR) {
+        ALOGE("%s: Failed to set native window buffer dimensions, error %s (%d).", __FUNCTION__,
+                strerror(-err), err);
+        return err;
+    }
+
+    err = native_window_set_buffers_format(anw.get(), pixelFmt);
+    if (err != NO_ERROR) {
+        ALOGE("%s: Failed to set native window buffer format, error %s (%d).", __FUNCTION__,
+                strerror(-err), err);
+        return err;
+    }
+
+    err = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN);
+    if (err != NO_ERROR) {
+        ALOGE("%s: Failed to set native window usage flag, error %s (%d).", __FUNCTION__,
+                strerror(-err), err);
+        return err;
+    }
+
+    int minUndequeuedBuffers;
+    err = anw.get()->query(anw.get(),
+            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+            &minUndequeuedBuffers);
+    if (err != NO_ERROR) {
+        ALOGE("%s: Failed to get native window min undequeued buffers, error %s (%d).",
+                __FUNCTION__, strerror(-err), err);
+        return err;
+    }
+
+    ALOGV("%s: Setting buffer count to %d", __FUNCTION__,
+          maxBufferSlack + 1 + minUndequeuedBuffers);
+    err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
+    if (err != NO_ERROR) {
+        ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
+                strerror(-err), err);
+        return err;
+    }
+    return NO_ERROR;
+}
+
+/**
+ * Produce a frame in the given surface.
+ *
+ * Args:
+ *    anw - a surface to produce a frame in.
+ *    pixelBuffer - image buffer to generate a frame from.
+ *    width - width of the pixelBuffer in pixels.
+ *    height - height of the pixelBuffer in pixels.
+ *    pixelFmt - format of the pixelBuffer, one of:
+ *               HAL_PIXEL_FORMAT_YCrCb_420_SP,
+ *               HAL_PIXEL_FORMAT_YCbCr_420_888,
+ *               HAL_PIXEL_FORMAT_BLOB
+ *    bufSize - the size of the pixelBuffer in bytes.
+ */
+static status_t produceFrame(const sp<ANativeWindow>& anw,
+                             uint8_t* pixelBuffer,
+                             int32_t width, // Width of the pixelBuffer
+                             int32_t height, // Height of the pixelBuffer
+                             int32_t pixelFmt, // Format of the pixelBuffer
+                             int64_t bufSize) {
+    ATRACE_CALL();
+    status_t err = NO_ERROR;
+    ANativeWindowBuffer* anb;
+    ALOGV("%s: Dequeue buffer from %p",__FUNCTION__, anw.get());
+
+    // TODO: Switch to using Surface::lock and Surface::unlockAndPost
+    err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
+    if (err != NO_ERROR) return err;
+
+    sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
+
+    switch(pixelFmt) {
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
+            if (bufSize < width * height * 4) {
+                ALOGE("%s: PixelBuffer size %lld to small for given dimensions", __FUNCTION__,
+                        bufSize);
+                return BAD_VALUE;
+            }
+            uint8_t* img = NULL;
+            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
+            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+            if (err != NO_ERROR) return err;
+
+            uint8_t* yPlane = img;
+            uint8_t* uPlane = img + height * width;
+            uint8_t* vPlane = uPlane + 1;
+            size_t chromaStep = 2;
+            size_t yStride = width;
+            size_t chromaStride = width;
+
+            rgbToYuv420(pixelBuffer, width, height, yPlane,
+                    uPlane, vPlane, chromaStep, yStride, chromaStride);
+            break;
+        }
+        case HAL_PIXEL_FORMAT_YCbCr_420_888: {
+            // Software writes with YCbCr_420_888 format are unsupported
+            // by the gralloc module for now
+            if (bufSize < width * height * 4) {
+                ALOGE("%s: PixelBuffer size %lld to small for given dimensions", __FUNCTION__,
+                      bufSize);
+                return BAD_VALUE;
+            }
+            android_ycbcr ycbcr = android_ycbcr();
+            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
+
+            err = buf->lockYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr);
+            if (err != NO_ERROR) {
+                ALOGE("%s: Failed to lock ycbcr buffer, error %s (%d).", __FUNCTION__,
+                        strerror(-err), err);
+                return err;
+            }
+            rgbToYuv420(pixelBuffer, width, height, &ycbcr);
+            break;
+        }
+        case HAL_PIXEL_FORMAT_BLOB: {
+            if (bufSize != width || height != 1) {
+                ALOGE("%s: Incorrect pixelBuffer size: %lld", __FUNCTION__, bufSize);
+                return BAD_VALUE;
+            }
+            int8_t* img = NULL;
+
+            ALOGV("%s: Lock buffer from %p for write", __FUNCTION__, anw.get());
+            err = buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+            if (err != NO_ERROR) {
+                ALOGE("%s: Failed to lock buffer, error %s (%d).", __FUNCTION__, strerror(-err),
+                        err);
+                return err;
+            }
+            memcpy(img, pixelBuffer, width);
+            break;
+        }
+        default: {
+            ALOGE("%s: Invalid pixel format in produceFrame: %x", __FUNCTION__, pixelFmt);
+            return BAD_VALUE;
+        }
+    }
+
+    ALOGV("%s: Unlock buffer from %p", __FUNCTION__, anw.get());
+    err = buf->unlock();
+    if (err != NO_ERROR) {
+        ALOGE("%s: Failed to unlock buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
+        return err;
+    }
+
+    ALOGV("%s: Queue buffer to %p", __FUNCTION__, anw.get());
+    err = anw->queueBuffer(anw.get(), buf->getNativeBuffer(), /*fenceFd*/-1);
+    if (err != NO_ERROR) {
+        ALOGE("%s: Failed to queue buffer, error %s (%d).", __FUNCTION__, strerror(-err), err);
+        return err;
+    }
+    return NO_ERROR;
+}
+
+static sp<ANativeWindow> getNativeWindow(JNIEnv* env, jobject surface) {
+    sp<ANativeWindow> anw;
+    if (surface) {
+        anw = android_view_Surface_getNativeWindow(env, surface);
+        if (env->ExceptionCheck()) {
+            return anw;
+        }
+    } else {
+        jniThrowNullPointerException(env, "surface");
+        return anw;
+    }
+    if (anw == NULL) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalArgumentException",
+                "Surface had no valid native window.");
+        return anw;
+    }
+    return anw;
+}
+
+extern "C" {
+
+static jint LegacyCameraDevice_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) {
+    ALOGV("nativeDetectSurfaceType");
+    sp<ANativeWindow> anw;
+    if ((anw = getNativeWindow(env, surface)) == NULL) {
+        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
+        return 0;
+    }
+    int32_t fmt = 0;
+    status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt);
+    if(err != NO_ERROR) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                                "Error while querying surface pixel format (error code %d)", err);
+        return 0;
+    }
+    return fmt;
+}
+
+static void LegacyCameraDevice_nativeDetectSurfaceDimens(JNIEnv* env, jobject thiz,
+          jobject surface, jintArray dimens) {
+    ALOGV("nativeGetSurfaceDimens");
+    sp<ANativeWindow> anw;
+    if ((anw = getNativeWindow(env, surface)) == NULL) {
+        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
+        return;
+    }
+    int32_t dimenBuf[2];
+    status_t err = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, dimenBuf);
+    if(err != NO_ERROR) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                        "Error while querying surface width (error code %d)", err);
+        return;
+    }
+    err = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, dimenBuf + 1);
+    if(err != NO_ERROR) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                "Error while querying surface height (error code %d)", err);
+        return;
+    }
+    env->SetIntArrayRegion(dimens, /*start*/0, /*length*/ARRAY_SIZE(dimenBuf), dimenBuf);
+}
+
+static void LegacyCameraDevice_nativeConfigureSurface(JNIEnv* env, jobject thiz, jobject surface,
+        jint width, jint height, jint pixelFormat) {
+    ALOGV("nativeConfigureSurface");
+    sp<ANativeWindow> anw;
+    if ((anw = getNativeWindow(env, surface)) == NULL) {
+        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
+        return;
+    }
+    status_t err = configureSurface(anw, width, height, pixelFormat, CAMERA_DEVICE_BUFFER_SLACK);
+    if (err != NO_ERROR) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                "Error while producing frame (error code %d)", err);
+        return;
+    }
+}
+
+static void LegacyCameraDevice_nativeProduceFrame(JNIEnv* env, jobject thiz, jobject surface,
+        jbyteArray pixelBuffer, jint width, jint height, jint pixelFormat) {
+    ALOGV("nativeProduceFrame");
+    sp<ANativeWindow> anw;
+
+    if ((anw = getNativeWindow(env, surface)) == NULL) {
+        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
+        return;
+    }
+
+    if (pixelBuffer == NULL) {
+        jniThrowNullPointerException(env, "pixelBuffer");
+        return;
+    }
+
+    int32_t bufSize = static_cast<int32_t>(env->GetArrayLength(pixelBuffer));
+    jbyte* pixels = env->GetByteArrayElements(pixelBuffer, /*is_copy*/NULL);
+
+    if (pixels == NULL) {
+        jniThrowNullPointerException(env, "pixels");
+        return;
+    }
+
+    status_t err = produceFrame(anw, reinterpret_cast<uint8_t*>(pixels), width, height,
+            pixelFormat, bufSize);
+    env->ReleaseByteArrayElements(pixelBuffer, pixels, JNI_ABORT);
+
+    if (err != NO_ERROR) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                "Error while producing frame (error code %d)", err);
+        return;
+    }
+}
+
+static void LegacyCameraDevice_nativeSetSurfaceFormat(JNIEnv* env, jobject thiz, jobject surface,
+        jint pixelFormat) {
+    ALOGV("nativeSetSurfaceType");
+    sp<ANativeWindow> anw;
+    if ((anw = getNativeWindow(env, surface)) == NULL) {
+        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
+        return;
+    }
+    status_t err = native_window_set_buffers_format(anw.get(), pixelFormat);
+    if (err != NO_ERROR) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                "Error while setting surface format (error code %d)", err);
+        return;
+    }
+}
+
+static void LegacyCameraDevice_nativeSetSurfaceDimens(JNIEnv* env, jobject thiz, jobject surface,
+        jint width, jint height) {
+    ALOGV("nativeSetSurfaceDimens");
+    sp<ANativeWindow> anw;
+    if ((anw = getNativeWindow(env, surface)) == NULL) {
+        ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__);
+        return;
+    }
+    status_t err = native_window_set_buffers_dimensions(anw.get(), width, height);
+    if (err != NO_ERROR) {
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                "Error while setting surface format (error code %d)", err);
+        return;
+    }
+}
+
+} // extern "C"
+
+static JNINativeMethod gCameraDeviceMethods[] = {
+    { "nativeDetectSurfaceType",
+    "(Landroid/view/Surface;)I",
+    (void *)LegacyCameraDevice_nativeDetectSurfaceType },
+    { "nativeDetectSurfaceDimens",
+    "(Landroid/view/Surface;[I)V",
+    (void *)LegacyCameraDevice_nativeDetectSurfaceDimens },
+    { "nativeConfigureSurface",
+    "(Landroid/view/Surface;III)V",
+    (void *)LegacyCameraDevice_nativeConfigureSurface },
+    { "nativeProduceFrame",
+    "(Landroid/view/Surface;[BIII)V",
+    (void *)LegacyCameraDevice_nativeProduceFrame },
+    { "nativeSetSurfaceFormat",
+    "(Landroid/view/Surface;I)V",
+    (void *)LegacyCameraDevice_nativeSetSurfaceFormat },
+    { "nativeSetSurfaceDimens",
+    "(Landroid/view/Surface;II)V",
+    (void *)LegacyCameraDevice_nativeSetSurfaceDimens },
+};
+
+// Get all the required offsets in java class and register native functions
+int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv* env)
+{
+    // Register native functions
+    return AndroidRuntime::registerNativeMethods(env,
+            CAMERA_DEVICE_CLASS_NAME,
+            gCameraDeviceMethods,
+            NELEM(gCameraDeviceMethods));
+}
+
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index 21e19e1..0a39a8e 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -20,8 +20,8 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
-#include "jni.h"
-#include "JNIHelp.h"
+#include <jni.h>
+#include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 #include <assert.h>
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index bc83234..83d9bda 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -20,8 +20,8 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
-#include "jni.h"
-#include "JNIHelp.h"
+#include <jni.h>
+#include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 #include <assert.h>
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index a45f269..a292cf2 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -20,8 +20,8 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
-#include "jni.h"
-#include "JNIHelp.h"
+#include <jni.h>
+#include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 #include <assert.h>
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index 05728ef..4ee5f15 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -20,8 +20,8 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
-#include "jni.h"
-#include "JNIHelp.h"
+#include <jni.h>
+#include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 #include <assert.h>
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index d3e5014..60ab37b 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -20,8 +20,8 @@
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
-#include "jni.h"
-#include "JNIHelp.h"
+#include <jni.h>
+#include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 #include <assert.h>
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index 8821352..ba324b0 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -20,8 +20,8 @@
 #include <GLES3/gl3.h>
 #include <GLES3/gl3ext.h>
 
-#include "jni.h"
-#include "JNIHelp.h"
+#include <jni.h>
+#include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <utils/misc.h>
 #include <assert.h>
diff --git a/core/jni/android_opengl_GLES31.cpp b/core/jni/android_opengl_GLES31.cpp
new file mode 100644
index 0000000..bc9fc5d
--- /dev/null
+++ b/core/jni/android_opengl_GLES31.cpp
@@ -0,0 +1,3168 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This source file is automatically generated
+
+#include <stdint.h>
+#include <GLES3/gl31.h>
+#include <jni.h>
+#include <JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/misc.h>
+#include <assert.h>
+
+static int initialized = 0;
+
+static jclass nioAccessClass;
+static jclass bufferClass;
+static jmethodID getBasePointerID;
+static jmethodID getBaseArrayID;
+static jmethodID getBaseArrayOffsetID;
+static jfieldID positionID;
+static jfieldID limitID;
+static jfieldID elementSizeShiftID;
+
+
+/* special calls implemented in Android's GLES wrapper used to more
+ * efficiently bound-check passed arrays */
+extern "C" {
+#ifdef GL_VERSION_ES_CM_1_1
+GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
+        const GLvoid *ptr, GLsizei count);
+GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
+        const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glPointSizePointerOESBounds(GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+#endif
+#ifdef GL_ES_VERSION_2_0
+static void glVertexAttribPointerBounds(GLuint indx, GLint size, GLenum type,
+        GLboolean normalized, GLsizei stride, const GLvoid *pointer, GLsizei count) {
+    glVertexAttribPointer(indx, size, type, normalized, stride, pointer);
+}
+#endif
+#ifdef GL_ES_VERSION_3_0
+static void glVertexAttribIPointerBounds(GLuint indx, GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count) {
+    glVertexAttribIPointer(indx, size, type, stride, pointer);
+}
+#endif
+}
+
+/* Cache method IDs each time the class is loaded. */
+
+static void
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
+{
+    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
+    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
+
+    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
+    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
+
+    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
+            "getBasePointer", "(Ljava/nio/Buffer;)J");
+    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
+    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
+
+    positionID = _env->GetFieldID(bufferClass, "position", "I");
+    limitID = _env->GetFieldID(bufferClass, "limit", "I");
+    elementSizeShiftID =
+        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
+}
+
+static void *
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
+{
+    jint position;
+    jint limit;
+    jint elementSizeShift;
+    jlong pointer;
+
+    position = _env->GetIntField(buffer, positionID);
+    limit = _env->GetIntField(buffer, limitID);
+    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+    *remaining = (limit - position) << elementSizeShift;
+    pointer = _env->CallStaticLongMethod(nioAccessClass,
+            getBasePointerID, buffer);
+    if (pointer != 0L) {
+        *array = NULL;
+        return reinterpret_cast<void*>(pointer);
+    }
+
+    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
+            getBaseArrayID, buffer);
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
+            getBaseArrayOffsetID, buffer);
+
+    return NULL;
+}
+
+static void
+releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
+{
+    _env->ReleasePrimitiveArrayCritical(array, data,
+                       commit ? 0 : JNI_ABORT);
+}
+
+static void *
+getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
+    char* buf = (char*) _env->GetDirectBufferAddress(buffer);
+    if (buf) {
+        jint position = _env->GetIntField(buffer, positionID);
+        jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+        buf += position << elementSizeShift;
+    } else {
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
+    }
+    return (void*) buf;
+}
+
+// --------------------------------------------------------------------------
+
+/*
+ * returns the number of values glGet returns for a given pname.
+ *
+ * The code below is written such that pnames requiring only one values
+ * are the default (and are not explicitely tested for). This makes the
+ * checking code much shorter/readable/efficient.
+ *
+ * This means that unknown pnames (e.g.: extensions) will default to 1. If
+ * that unknown pname needs more than 1 value, then the validation check
+ * is incomplete and the app may crash if it passed the wrong number params.
+ */
+static int getNeededCount(GLint pname) {
+    int needed = 1;
+#ifdef GL_ES_VERSION_2_0
+    // GLES 2.x pnames
+    switch (pname) {
+        case GL_ALIASED_LINE_WIDTH_RANGE:
+        case GL_ALIASED_POINT_SIZE_RANGE:
+            needed = 2;
+            break;
+
+        case GL_BLEND_COLOR:
+        case GL_COLOR_CLEAR_VALUE:
+        case GL_COLOR_WRITEMASK:
+        case GL_SCISSOR_BOX:
+        case GL_VIEWPORT:
+            needed = 4;
+            break;
+
+        case GL_COMPRESSED_TEXTURE_FORMATS:
+            glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &needed);
+            break;
+
+        case GL_SHADER_BINARY_FORMATS:
+            glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &needed);
+            break;
+    }
+#endif
+
+#ifdef GL_VERSION_ES_CM_1_1
+    // GLES 1.x pnames
+    switch (pname) {
+        case GL_ALIASED_LINE_WIDTH_RANGE:
+        case GL_ALIASED_POINT_SIZE_RANGE:
+        case GL_DEPTH_RANGE:
+        case GL_SMOOTH_LINE_WIDTH_RANGE:
+        case GL_SMOOTH_POINT_SIZE_RANGE:
+            needed = 2;
+            break;
+
+        case GL_CURRENT_NORMAL:
+        case GL_POINT_DISTANCE_ATTENUATION:
+            needed = 3;
+            break;
+
+        case GL_COLOR_CLEAR_VALUE:
+        case GL_COLOR_WRITEMASK:
+        case GL_CURRENT_COLOR:
+        case GL_CURRENT_TEXTURE_COORDS:
+        case GL_FOG_COLOR:
+        case GL_LIGHT_MODEL_AMBIENT:
+        case GL_SCISSOR_BOX:
+        case GL_VIEWPORT:
+            needed = 4;
+            break;
+
+        case GL_MODELVIEW_MATRIX:
+        case GL_PROJECTION_MATRIX:
+        case GL_TEXTURE_MATRIX:
+            needed = 16;
+            break;
+
+        case GL_COMPRESSED_TEXTURE_FORMATS:
+            glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &needed);
+            break;
+    }
+#endif
+    return needed;
+}
+
+template <typename JTYPEARRAY, typename CTYPE, void GET(GLenum, CTYPE*)>
+static void
+get
+  (JNIEnv *_env, jobject _this, jint pname, JTYPEARRAY params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    CTYPE *params_base = (CTYPE *) 0;
+    jint _remaining;
+    CTYPE *params = (CTYPE *) 0;
+    int _needed = 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    _needed = getNeededCount(pname);
+    // if we didn't find this pname, we just assume the user passed
+    // an array of the right size -- this might happen with extensions
+    // or if we forget an enum here.
+    if (_remaining < _needed) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
+        goto exit;
+    }
+    params_base = (CTYPE *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    GET(
+        (GLenum)pname,
+        (CTYPE *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+
+template <typename CTYPE, void GET(GLenum, CTYPE*)>
+static void
+getarray
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    CTYPE *params = (CTYPE *) 0;
+    int _needed = 0;
+
+    params = (CTYPE *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    _remaining /= sizeof(CTYPE);    // convert from bytes to item count
+    _needed = getNeededCount(pname);
+    // if we didn't find this pname, we just assume the user passed
+    // an array of the right size -- this might happen with extensions
+    // or if we forget an enum here.
+    if (_needed>0 && _remaining < _needed) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
+        goto exit;
+    }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (CTYPE *) (_paramsBase + _bufferOffset);
+    }
+    GET(
+        (GLenum)pname,
+        (CTYPE *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+// --------------------------------------------------------------------------
+/* void glDispatchCompute ( GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z ) */
+static void
+android_glDispatchCompute__III
+  (JNIEnv *_env, jobject _this, jint num_groups_x, jint num_groups_y, jint num_groups_z) {
+    glDispatchCompute(
+        (GLuint)num_groups_x,
+        (GLuint)num_groups_y,
+        (GLuint)num_groups_z
+    );
+}
+
+/* void glDispatchComputeIndirect ( GLintptr indirect ) */
+static void android_glDispatchComputeIndirect(JNIEnv *_env, jobject, jlong indirect) {
+    // 'indirect' is a byte offset, not a pointer. GL checks for negative and too-large values.
+    // Here we only need to check for successful 64-bit to 32-bit conversion.
+    // - jlong is a int64_t (jni.h)
+    // - GLintptr is a long (khrplatform.h)
+    if (sizeof(GLintptr) != sizeof(jlong) && (indirect < LONG_MIN || indirect > LONG_MAX)) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "indirect offset too large");
+        return;
+    }
+    glDispatchComputeIndirect((GLintptr)indirect);
+}
+
+/* void glDrawArraysIndirect ( GLenum mode, const void *indirect ) */
+static void android_glDrawArraysIndirect(JNIEnv *_env, jobject, int mode, jlong indirect) {
+    // In OpenGL ES, 'indirect' is a byte offset into a buffer, not a raw pointer.
+    // GL checks for too-large values. Here we only need to check for successful signed 64-bit
+    // to unsigned 32-bit conversion.
+    if (sizeof(void*) != sizeof(jlong) && indirect > UINTPTR_MAX) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "indirect offset too large");
+        return;
+    }
+    glDrawArraysIndirect(mode, (const void*)indirect);
+}
+
+/* void glDrawElementsIndirect ( GLenum mode, GLenum type, const void *indirect ) */
+static void android_glDrawElementsIndirect(JNIEnv *_env, jobject, jint mode, jint type, jlong indirect) {
+    // In OpenGL ES, 'indirect' is a byte offset into a buffer, not a raw pointer.
+    // GL checks for too-large values. Here we only need to check for successful signed 64-bit
+    // to unsigned 32-bit conversion.
+    if (sizeof(void*) != sizeof(jlong) && indirect > UINTPTR_MAX) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "indirect offset too large");
+        return;
+    }
+    glDrawElementsIndirect(mode, type, (const void*)indirect);
+}
+
+/* void glFramebufferParameteri ( GLenum target, GLenum pname, GLint param ) */
+static void
+android_glFramebufferParameteri__III
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jint param) {
+    glFramebufferParameteri(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint)param
+    );
+}
+
+/* void glGetFramebufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
+static void
+android_glGetFramebufferParameteriv__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetFramebufferParameteriv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetFramebufferParameteriv ( GLenum target, GLenum pname, GLint *params ) */
+static void
+android_glGetFramebufferParameteriv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
+    glGetFramebufferParameteriv(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_TRUE);
+    }
+}
+
+/* void glGetProgramInterfaceiv ( GLuint program, GLenum programInterface, GLenum pname, GLint *params ) */
+static void
+android_glGetProgramInterfaceiv__III_3II
+  (JNIEnv *_env, jobject _this, jint program, jint programInterface, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetProgramInterfaceiv(
+        (GLuint)program,
+        (GLenum)programInterface,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetProgramInterfaceiv ( GLuint program, GLenum programInterface, GLenum pname, GLint *params ) */
+static void
+android_glGetProgramInterfaceiv__IIILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint programInterface, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
+    glGetProgramInterfaceiv(
+        (GLuint)program,
+        (GLenum)programInterface,
+        (GLenum)pname,
+        (GLint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_TRUE);
+    }
+}
+
+/* GLuint glGetProgramResourceIndex ( GLuint program, GLenum programInterface, const GLchar *name ) */
+static jint
+android_glGetProgramResourceIndex__IILjava_lang_String_2
+  (JNIEnv *_env, jobject _this, jint program, jint programInterface, jstring name) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint _returnValue = 0;
+    const char* _nativename = 0;
+
+    if (!name) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
+        goto exit;
+    }
+    _nativename = _env->GetStringUTFChars(name, 0);
+
+    _returnValue = glGetProgramResourceIndex(
+        (GLuint)program,
+        (GLenum)programInterface,
+        (GLchar *)_nativename
+    );
+
+exit:
+    if (_nativename) {
+        _env->ReleaseStringUTFChars(name, _nativename);
+    }
+
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return (jint)_returnValue;
+}
+
+/* void glGetProgramResourceName ( GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name ) */
+static jstring
+android_glGetProgramResourceName
+  (JNIEnv *_env, jobject _this, jint program, jint programInterface, jint index) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return NULL;
+}
+
+/* void glGetProgramResourceiv ( GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params ) */
+static void
+android_glGetProgramResourceiv__IIII_3III_3II_3II
+  (JNIEnv *_env, jobject _this, jint program, jint programInterface, jint index, jint propCount, jintArray props_ref, jint propsOffset, jint bufSize, jintArray length_ref, jint lengthOffset, jintArray params_ref, jint paramsOffset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLenum *props_base = (GLenum *) 0;
+    jint _propsRemaining;
+    GLenum *props = (GLenum *) 0;
+    GLsizei *length_base = (GLsizei *) 0;
+    jint _lengthRemaining;
+    GLsizei *length = (GLsizei *) 0;
+    GLint *params_base = (GLint *) 0;
+    jint _paramsRemaining;
+    GLint *params = (GLint *) 0;
+
+    if (!props_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "props == null";
+        goto exit;
+    }
+    if (propsOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "propsOffset < 0";
+        goto exit;
+    }
+    _propsRemaining = _env->GetArrayLength(props_ref) - propsOffset;
+    props_base = (GLenum *)
+        _env->GetPrimitiveArrayCritical(props_ref, (jboolean *)0);
+    props = props_base + propsOffset;
+
+    if (!length_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length == null";
+        goto exit;
+    }
+    if (lengthOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "lengthOffset < 0";
+        goto exit;
+    }
+    _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+    length_base = (GLsizei *)
+        _env->GetPrimitiveArrayCritical(length_ref, (jboolean *)0);
+    length = length_base + lengthOffset;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (paramsOffset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "paramsOffset < 0";
+        goto exit;
+    }
+    _paramsRemaining = _env->GetArrayLength(params_ref) - paramsOffset;
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + paramsOffset;
+
+    glGetProgramResourceiv(
+        (GLuint)program,
+        (GLenum)programInterface,
+        (GLuint)index,
+        (GLsizei)propCount,
+        (GLenum *)props,
+        (GLsizei)bufSize,
+        (GLsizei *)length,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (length_base) {
+        _env->ReleasePrimitiveArrayCritical(length_ref, length_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (props_base) {
+        _env->ReleasePrimitiveArrayCritical(props_ref, props_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetProgramResourceiv ( GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params ) */
+static void
+android_glGetProgramResourceiv__IIIILjava_nio_IntBuffer_2ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint programInterface, jint index, jint propCount, jobject props_buf, jint bufSize, jobject length_buf, jobject params_buf) {
+    jarray _propsArray = (jarray) 0;
+    jint _propsBufferOffset = (jint) 0;
+    jarray _lengthArray = (jarray) 0;
+    jint _lengthBufferOffset = (jint) 0;
+    jarray _paramsArray = (jarray) 0;
+    jint _paramsBufferOffset = (jint) 0;
+    jint _propsRemaining;
+    GLenum *props = (GLenum *) 0;
+    jint _lengthRemaining;
+    GLsizei *length = (GLsizei *) 0;
+    jint _paramsRemaining;
+    GLint *params = (GLint *) 0;
+
+    props = (GLenum *)getPointer(_env, props_buf, &_propsArray, &_propsRemaining, &_propsBufferOffset);
+    length = (GLsizei *)getPointer(_env, length_buf, &_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
+    params = (GLint *)getPointer(_env, params_buf, &_paramsArray, &_paramsRemaining, &_paramsBufferOffset);
+    if (props == NULL) {
+        char * _propsBase = (char *)_env->GetPrimitiveArrayCritical(_propsArray, (jboolean *) 0);
+        props = (GLenum *) (_propsBase + _propsBufferOffset);
+    }
+    if (length == NULL) {
+        char * _lengthBase = (char *)_env->GetPrimitiveArrayCritical(_lengthArray, (jboolean *) 0);
+        length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
+    }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_paramsArray, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _paramsBufferOffset);
+    }
+    glGetProgramResourceiv(
+        (GLuint)program,
+        (GLenum)programInterface,
+        (GLuint)index,
+        (GLsizei)propCount,
+        (GLenum *)props,
+        (GLsizei)bufSize,
+        (GLsizei *)length,
+        (GLint *)params
+    );
+    if (_paramsArray) {
+        releasePointer(_env, _paramsArray, params, JNI_TRUE);
+    }
+    if (_lengthArray) {
+        releasePointer(_env, _lengthArray, length, JNI_TRUE);
+    }
+    if (_propsArray) {
+        releasePointer(_env, _propsArray, props, JNI_FALSE);
+    }
+}
+
+/* GLint glGetProgramResourceLocation ( GLuint program, GLenum programInterface, const GLchar *name ) */
+static jint
+android_glGetProgramResourceLocation__IILjava_lang_String_2
+  (JNIEnv *_env, jobject _this, jint program, jint programInterface, jstring name) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint _returnValue = 0;
+    const char* _nativename = 0;
+
+    if (!name) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "name == null";
+        goto exit;
+    }
+    _nativename = _env->GetStringUTFChars(name, 0);
+
+    _returnValue = glGetProgramResourceLocation(
+        (GLuint)program,
+        (GLenum)programInterface,
+        (GLchar *)_nativename
+    );
+
+exit:
+    if (_nativename) {
+        _env->ReleaseStringUTFChars(name, _nativename);
+    }
+
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return (jint)_returnValue;
+}
+
+/* void glUseProgramStages ( GLuint pipeline, GLbitfield stages, GLuint program ) */
+static void
+android_glUseProgramStages__III
+  (JNIEnv *_env, jobject _this, jint pipeline, jint stages, jint program) {
+    glUseProgramStages(
+        (GLuint)pipeline,
+        (GLbitfield)stages,
+        (GLuint)program
+    );
+}
+
+/* void glActiveShaderProgram ( GLuint pipeline, GLuint program ) */
+static void
+android_glActiveShaderProgram__II
+  (JNIEnv *_env, jobject _this, jint pipeline, jint program) {
+    glActiveShaderProgram(
+        (GLuint)pipeline,
+        (GLuint)program
+    );
+}
+
+/* GLuint glCreateShaderProgramv ( GLenum type, GLsizei count, const GLchar *const *strings ) */
+static jint
+android_glCreateShaderProgramv
+  (JNIEnv *_env, jobject _this, jint type, jobjectArray strings) {
+
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return 0;
+}
+/* void glBindProgramPipeline ( GLuint pipeline ) */
+static void
+android_glBindProgramPipeline__I
+  (JNIEnv *_env, jobject _this, jint pipeline) {
+    glBindProgramPipeline(
+        (GLuint)pipeline
+    );
+}
+
+/* void glDeleteProgramPipelines ( GLsizei n, const GLuint *pipelines ) */
+static void
+android_glDeleteProgramPipelines__I_3II
+  (JNIEnv *_env, jobject _this, jint n, jintArray pipelines_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint *pipelines_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *pipelines = (GLuint *) 0;
+
+    if (!pipelines_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "pipelines == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(pipelines_ref) - offset;
+    pipelines_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(pipelines_ref, (jboolean *)0);
+    pipelines = pipelines_base + offset;
+
+    glDeleteProgramPipelines(
+        (GLsizei)n,
+        (GLuint *)pipelines
+    );
+
+exit:
+    if (pipelines_base) {
+        _env->ReleasePrimitiveArrayCritical(pipelines_ref, pipelines_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glDeleteProgramPipelines ( GLsizei n, const GLuint *pipelines ) */
+static void
+android_glDeleteProgramPipelines__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint n, jobject pipelines_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLuint *pipelines = (GLuint *) 0;
+
+    pipelines = (GLuint *)getPointer(_env, pipelines_buf, &_array, &_remaining, &_bufferOffset);
+    if (pipelines == NULL) {
+        char * _pipelinesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pipelines = (GLuint *) (_pipelinesBase + _bufferOffset);
+    }
+    glDeleteProgramPipelines(
+        (GLsizei)n,
+        (GLuint *)pipelines
+    );
+    if (_array) {
+        releasePointer(_env, _array, pipelines, JNI_FALSE);
+    }
+}
+
+/* void glGenProgramPipelines ( GLsizei n, GLuint *pipelines ) */
+static void
+android_glGenProgramPipelines__I_3II
+  (JNIEnv *_env, jobject _this, jint n, jintArray pipelines_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint *pipelines_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *pipelines = (GLuint *) 0;
+
+    if (!pipelines_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "pipelines == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(pipelines_ref) - offset;
+    pipelines_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(pipelines_ref, (jboolean *)0);
+    pipelines = pipelines_base + offset;
+
+    glGenProgramPipelines(
+        (GLsizei)n,
+        (GLuint *)pipelines
+    );
+
+exit:
+    if (pipelines_base) {
+        _env->ReleasePrimitiveArrayCritical(pipelines_ref, pipelines_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGenProgramPipelines ( GLsizei n, GLuint *pipelines ) */
+static void
+android_glGenProgramPipelines__ILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint n, jobject pipelines_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLuint *pipelines = (GLuint *) 0;
+
+    pipelines = (GLuint *)getPointer(_env, pipelines_buf, &_array, &_remaining, &_bufferOffset);
+    if (pipelines == NULL) {
+        char * _pipelinesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        pipelines = (GLuint *) (_pipelinesBase + _bufferOffset);
+    }
+    glGenProgramPipelines(
+        (GLsizei)n,
+        (GLuint *)pipelines
+    );
+    if (_array) {
+        releasePointer(_env, _array, pipelines, JNI_TRUE);
+    }
+}
+
+/* GLboolean glIsProgramPipeline ( GLuint pipeline ) */
+static jboolean
+android_glIsProgramPipeline__I
+  (JNIEnv *_env, jobject _this, jint pipeline) {
+    GLboolean _returnValue;
+    _returnValue = glIsProgramPipeline(
+        (GLuint)pipeline
+    );
+    return (jboolean)_returnValue;
+}
+
+/* void glGetProgramPipelineiv ( GLuint pipeline, GLenum pname, GLint *params ) */
+static void
+android_glGetProgramPipelineiv__II_3II
+  (JNIEnv *_env, jobject _this, jint pipeline, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetProgramPipelineiv(
+        (GLuint)pipeline,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetProgramPipelineiv ( GLuint pipeline, GLenum pname, GLint *params ) */
+static void
+android_glGetProgramPipelineiv__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint pipeline, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
+    glGetProgramPipelineiv(
+        (GLuint)pipeline,
+        (GLenum)pname,
+        (GLint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_TRUE);
+    }
+}
+
+/* void glProgramUniform1i ( GLuint program, GLint location, GLint v0 ) */
+static void
+android_glProgramUniform1i__III
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint v0) {
+    glProgramUniform1i(
+        (GLuint)program,
+        (GLint)location,
+        (GLint)v0
+    );
+}
+
+/* void glProgramUniform2i ( GLuint program, GLint location, GLint v0, GLint v1 ) */
+static void
+android_glProgramUniform2i__IIII
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint v0, jint v1) {
+    glProgramUniform2i(
+        (GLuint)program,
+        (GLint)location,
+        (GLint)v0,
+        (GLint)v1
+    );
+}
+
+/* void glProgramUniform3i ( GLuint program, GLint location, GLint v0, GLint v1, GLint v2 ) */
+static void
+android_glProgramUniform3i__IIIII
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint v0, jint v1, jint v2) {
+    glProgramUniform3i(
+        (GLuint)program,
+        (GLint)location,
+        (GLint)v0,
+        (GLint)v1,
+        (GLint)v2
+    );
+}
+
+/* void glProgramUniform4i ( GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3 ) */
+static void
+android_glProgramUniform4i__IIIIII
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint v0, jint v1, jint v2, jint v3) {
+    glProgramUniform4i(
+        (GLuint)program,
+        (GLint)location,
+        (GLint)v0,
+        (GLint)v1,
+        (GLint)v2,
+        (GLint)v3
+    );
+}
+
+/* void glProgramUniform1ui ( GLuint program, GLint location, GLuint v0 ) */
+static void
+android_glProgramUniform1ui__III
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint v0) {
+    glProgramUniform1ui(
+        (GLuint)program,
+        (GLint)location,
+        (GLuint)v0
+    );
+}
+
+/* void glProgramUniform2ui ( GLuint program, GLint location, GLuint v0, GLuint v1 ) */
+static void
+android_glProgramUniform2ui__IIII
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint v0, jint v1) {
+    glProgramUniform2ui(
+        (GLuint)program,
+        (GLint)location,
+        (GLuint)v0,
+        (GLuint)v1
+    );
+}
+
+/* void glProgramUniform3ui ( GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2 ) */
+static void
+android_glProgramUniform3ui__IIIII
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint v0, jint v1, jint v2) {
+    glProgramUniform3ui(
+        (GLuint)program,
+        (GLint)location,
+        (GLuint)v0,
+        (GLuint)v1,
+        (GLuint)v2
+    );
+}
+
+/* void glProgramUniform4ui ( GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3 ) */
+static void
+android_glProgramUniform4ui__IIIIII
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint v0, jint v1, jint v2, jint v3) {
+    glProgramUniform4ui(
+        (GLuint)program,
+        (GLint)location,
+        (GLuint)v0,
+        (GLuint)v1,
+        (GLuint)v2,
+        (GLuint)v3
+    );
+}
+
+/* void glProgramUniform1f ( GLuint program, GLint location, GLfloat v0 ) */
+static void
+android_glProgramUniform1f__IIF
+  (JNIEnv *_env, jobject _this, jint program, jint location, jfloat v0) {
+    glProgramUniform1f(
+        (GLuint)program,
+        (GLint)location,
+        (GLfloat)v0
+    );
+}
+
+/* void glProgramUniform2f ( GLuint program, GLint location, GLfloat v0, GLfloat v1 ) */
+static void
+android_glProgramUniform2f__IIFF
+  (JNIEnv *_env, jobject _this, jint program, jint location, jfloat v0, jfloat v1) {
+    glProgramUniform2f(
+        (GLuint)program,
+        (GLint)location,
+        (GLfloat)v0,
+        (GLfloat)v1
+    );
+}
+
+/* void glProgramUniform3f ( GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2 ) */
+static void
+android_glProgramUniform3f__IIFFF
+  (JNIEnv *_env, jobject _this, jint program, jint location, jfloat v0, jfloat v1, jfloat v2) {
+    glProgramUniform3f(
+        (GLuint)program,
+        (GLint)location,
+        (GLfloat)v0,
+        (GLfloat)v1,
+        (GLfloat)v2
+    );
+}
+
+/* void glProgramUniform4f ( GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3 ) */
+static void
+android_glProgramUniform4f__IIFFFF
+  (JNIEnv *_env, jobject _this, jint program, jint location, jfloat v0, jfloat v1, jfloat v2, jfloat v3) {
+    glProgramUniform4f(
+        (GLuint)program,
+        (GLint)location,
+        (GLfloat)v0,
+        (GLfloat)v1,
+        (GLfloat)v2,
+        (GLfloat)v3
+    );
+}
+
+/* void glProgramUniform1iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
+static void
+android_glProgramUniform1iv__III_3II
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *value_base = (GLint *) 0;
+    jint _remaining;
+    GLint *value = (GLint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform1iv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform1iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
+static void
+android_glProgramUniform1iv__IIILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *value = (GLint *) 0;
+
+    value = (GLint *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLint *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform1iv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLint *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniform2iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
+static void
+android_glProgramUniform2iv__III_3II
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *value_base = (GLint *) 0;
+    jint _remaining;
+    GLint *value = (GLint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform2iv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform2iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
+static void
+android_glProgramUniform2iv__IIILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *value = (GLint *) 0;
+
+    value = (GLint *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLint *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform2iv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLint *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniform3iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
+static void
+android_glProgramUniform3iv__III_3II
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *value_base = (GLint *) 0;
+    jint _remaining;
+    GLint *value = (GLint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform3iv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform3iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
+static void
+android_glProgramUniform3iv__IIILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *value = (GLint *) 0;
+
+    value = (GLint *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLint *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform3iv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLint *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniform4iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
+static void
+android_glProgramUniform4iv__III_3II
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *value_base = (GLint *) 0;
+    jint _remaining;
+    GLint *value = (GLint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform4iv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform4iv ( GLuint program, GLint location, GLsizei count, const GLint *value ) */
+static void
+android_glProgramUniform4iv__IIILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *value = (GLint *) 0;
+
+    value = (GLint *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLint *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform4iv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLint *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniform1uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
+static void
+android_glProgramUniform1uiv__III_3II
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint *value_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *value = (GLuint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform1uiv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLuint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform1uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
+static void
+android_glProgramUniform1uiv__IIILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLuint *value = (GLuint *) 0;
+
+    value = (GLuint *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLuint *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform1uiv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLuint *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniform2uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
+static void
+android_glProgramUniform2uiv__III_3II
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint *value_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *value = (GLuint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform2uiv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLuint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform2uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
+static void
+android_glProgramUniform2uiv__IIILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLuint *value = (GLuint *) 0;
+
+    value = (GLuint *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLuint *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform2uiv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLuint *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniform3uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
+static void
+android_glProgramUniform3uiv__III_3II
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint *value_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *value = (GLuint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform3uiv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLuint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform3uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
+static void
+android_glProgramUniform3uiv__IIILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLuint *value = (GLuint *) 0;
+
+    value = (GLuint *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLuint *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform3uiv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLuint *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniform4uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
+static void
+android_glProgramUniform4uiv__III_3II
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jintArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint *value_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *value = (GLuint *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform4uiv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLuint *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform4uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value ) */
+static void
+android_glProgramUniform4uiv__IIILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLuint *value = (GLuint *) 0;
+
+    value = (GLuint *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLuint *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform4uiv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLuint *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniform1fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
+static void
+android_glProgramUniform1fv__III_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform1fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform1fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
+static void
+android_glProgramUniform1fv__IIILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform1fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniform2fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
+static void
+android_glProgramUniform2fv__III_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform2fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform2fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
+static void
+android_glProgramUniform2fv__IIILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform2fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniform3fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
+static void
+android_glProgramUniform3fv__III_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform3fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform3fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
+static void
+android_glProgramUniform3fv__IIILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform3fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniform4fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
+static void
+android_glProgramUniform4fv__III_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniform4fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniform4fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value ) */
+static void
+android_glProgramUniform4fv__IIILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniform4fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniformMatrix2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix2fv__IIIZ_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniformMatrix2fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniformMatrix2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix2fv__IIIZLjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniformMatrix2fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniformMatrix3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix3fv__IIIZ_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniformMatrix3fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniformMatrix3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix3fv__IIIZLjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniformMatrix3fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniformMatrix4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix4fv__IIIZ_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniformMatrix4fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniformMatrix4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix4fv__IIIZLjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniformMatrix4fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniformMatrix2x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix2x3fv__IIIZ_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniformMatrix2x3fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniformMatrix2x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix2x3fv__IIIZLjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniformMatrix2x3fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniformMatrix3x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix3x2fv__IIIZ_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniformMatrix3x2fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniformMatrix3x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix3x2fv__IIIZLjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniformMatrix3x2fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniformMatrix2x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix2x4fv__IIIZ_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniformMatrix2x4fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniformMatrix2x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix2x4fv__IIIZLjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniformMatrix2x4fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniformMatrix4x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix4x2fv__IIIZ_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniformMatrix4x2fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniformMatrix4x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix4x2fv__IIIZLjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniformMatrix4x2fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniformMatrix3x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix3x4fv__IIIZ_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniformMatrix3x4fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniformMatrix3x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix3x4fv__IIIZLjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniformMatrix3x4fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glProgramUniformMatrix4x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix4x3fv__IIIZ_3FI
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jfloatArray value_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *value_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    if (!value_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "value == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(value_ref) - offset;
+    value_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(value_ref, (jboolean *)0);
+    value = value_base + offset;
+
+    glProgramUniformMatrix4x3fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+
+exit:
+    if (value_base) {
+        _env->ReleasePrimitiveArrayCritical(value_ref, value_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glProgramUniformMatrix4x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value ) */
+static void
+android_glProgramUniformMatrix4x3fv__IIIZLjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint location, jint count, jboolean transpose, jobject value_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *value = (GLfloat *) 0;
+
+    value = (GLfloat *)getPointer(_env, value_buf, &_array, &_remaining, &_bufferOffset);
+    if (value == NULL) {
+        char * _valueBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        value = (GLfloat *) (_valueBase + _bufferOffset);
+    }
+    glProgramUniformMatrix4x3fv(
+        (GLuint)program,
+        (GLint)location,
+        (GLsizei)count,
+        (GLboolean)transpose,
+        (GLfloat *)value
+    );
+    if (_array) {
+        releasePointer(_env, _array, value, JNI_FALSE);
+    }
+}
+
+/* void glValidateProgramPipeline ( GLuint pipeline ) */
+static void
+android_glValidateProgramPipeline__I
+  (JNIEnv *_env, jobject _this, jint pipeline) {
+    glValidateProgramPipeline(
+        (GLuint)pipeline
+    );
+}
+
+#include <stdlib.h>
+
+/* void glGetProgramPipelineInfoLog ( GLuint shader, GLsizei maxLength, GLsizei* length, GLchar* infoLog ) */
+static jstring android_glGetProgramPipelineInfoLog(JNIEnv *_env, jobject, jint shader) {
+    GLint infoLen = 0;
+    glGetProgramPipelineiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+    if (!infoLen) {
+        return _env->NewStringUTF("");
+    }
+    char* buf = (char*) malloc(infoLen);
+    if (buf == NULL) {
+        jniThrowException(_env, "java/lang/OutOfMemoryError", "out of memory");
+        return NULL;
+    }
+    glGetProgramPipelineInfoLog(shader, infoLen, NULL, buf);
+    jstring result = _env->NewStringUTF(buf);
+    free(buf);
+    return result;
+}
+/* void glBindImageTexture ( GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format ) */
+static void
+android_glBindImageTexture__IIIZIII
+  (JNIEnv *_env, jobject _this, jint unit, jint texture, jint level, jboolean layered, jint layer, jint access, jint format) {
+    glBindImageTexture(
+        (GLuint)unit,
+        (GLuint)texture,
+        (GLint)level,
+        (GLboolean)layered,
+        (GLint)layer,
+        (GLenum)access,
+        (GLenum)format
+    );
+}
+
+/* void glGetBooleani_v ( GLenum target, GLuint index, GLboolean *data ) */
+static void
+android_glGetBooleani_v__II_3ZI
+  (JNIEnv *_env, jobject _this, jint target, jint index, jbooleanArray data_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLboolean *data_base = (GLboolean *) 0;
+    jint _remaining;
+    GLboolean *data = (GLboolean *) 0;
+
+    if (!data_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "data == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(data_ref) - offset;
+    data_base = (GLboolean *)
+        _env->GetPrimitiveArrayCritical(data_ref, (jboolean *)0);
+    data = data_base + offset;
+
+    glGetBooleani_v(
+        (GLenum)target,
+        (GLuint)index,
+        (GLboolean *)data
+    );
+
+exit:
+    if (data_base) {
+        _env->ReleasePrimitiveArrayCritical(data_ref, data_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetBooleani_v ( GLenum target, GLuint index, GLboolean *data ) */
+static void
+android_glGetBooleani_v__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint index, jobject data_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLboolean *data = (GLboolean *) 0;
+
+    data = (GLboolean *)getPointer(_env, data_buf, &_array, &_remaining, &_bufferOffset);
+    if (data == NULL) {
+        char * _dataBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        data = (GLboolean *) (_dataBase + _bufferOffset);
+    }
+    glGetBooleani_v(
+        (GLenum)target,
+        (GLuint)index,
+        (GLboolean *)data
+    );
+    if (_array) {
+        releasePointer(_env, _array, data, JNI_TRUE);
+    }
+}
+
+/* void glMemoryBarrier ( GLbitfield barriers ) */
+static void
+android_glMemoryBarrier__I
+  (JNIEnv *_env, jobject _this, jint barriers) {
+    glMemoryBarrier(
+        (GLbitfield)barriers
+    );
+}
+
+/* void glMemoryBarrierByRegion ( GLbitfield barriers ) */
+static void
+android_glMemoryBarrierByRegion__I
+  (JNIEnv *_env, jobject _this, jint barriers) {
+    glMemoryBarrierByRegion(
+        (GLbitfield)barriers
+    );
+}
+
+/* void glTexStorage2DMultisample ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations ) */
+static void
+android_glTexStorage2DMultisample__IIIIIZ
+  (JNIEnv *_env, jobject _this, jint target, jint samples, jint internalformat, jint width, jint height, jboolean fixedsamplelocations) {
+    glTexStorage2DMultisample(
+        (GLenum)target,
+        (GLsizei)samples,
+        (GLenum)internalformat,
+        (GLsizei)width,
+        (GLsizei)height,
+        (GLboolean)fixedsamplelocations
+    );
+}
+
+/* void glGetMultisamplefv ( GLenum pname, GLuint index, GLfloat *val ) */
+static void
+android_glGetMultisamplefv__II_3FI
+  (JNIEnv *_env, jobject _this, jint pname, jint index, jfloatArray val_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *val_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *val = (GLfloat *) 0;
+
+    if (!val_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "val == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(val_ref) - offset;
+    val_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(val_ref, (jboolean *)0);
+    val = val_base + offset;
+
+    glGetMultisamplefv(
+        (GLenum)pname,
+        (GLuint)index,
+        (GLfloat *)val
+    );
+
+exit:
+    if (val_base) {
+        _env->ReleasePrimitiveArrayCritical(val_ref, val_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetMultisamplefv ( GLenum pname, GLuint index, GLfloat *val ) */
+static void
+android_glGetMultisamplefv__IILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint pname, jint index, jobject val_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *val = (GLfloat *) 0;
+
+    val = (GLfloat *)getPointer(_env, val_buf, &_array, &_remaining, &_bufferOffset);
+    if (val == NULL) {
+        char * _valBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        val = (GLfloat *) (_valBase + _bufferOffset);
+    }
+    glGetMultisamplefv(
+        (GLenum)pname,
+        (GLuint)index,
+        (GLfloat *)val
+    );
+    if (_array) {
+        releasePointer(_env, _array, val, JNI_TRUE);
+    }
+}
+
+/* void glSampleMaski ( GLuint maskNumber, GLbitfield mask ) */
+static void
+android_glSampleMaski__II
+  (JNIEnv *_env, jobject _this, jint maskNumber, jint mask) {
+    glSampleMaski(
+        (GLuint)maskNumber,
+        (GLbitfield)mask
+    );
+}
+
+/* void glGetTexLevelParameteriv ( GLenum target, GLint level, GLenum pname, GLint *params ) */
+static void
+android_glGetTexLevelParameteriv__III_3II
+  (JNIEnv *_env, jobject _this, jint target, jint level, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexLevelParameteriv(
+        (GLenum)target,
+        (GLint)level,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetTexLevelParameteriv ( GLenum target, GLint level, GLenum pname, GLint *params ) */
+static void
+android_glGetTexLevelParameteriv__IIILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint level, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
+    glGetTexLevelParameteriv(
+        (GLenum)target,
+        (GLint)level,
+        (GLenum)pname,
+        (GLint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_TRUE);
+    }
+}
+
+/* void glGetTexLevelParameterfv ( GLenum target, GLint level, GLenum pname, GLfloat *params ) */
+static void
+android_glGetTexLevelParameterfv__III_3FI
+  (JNIEnv *_env, jobject _this, jint target, jint level, jint pname, jfloatArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLfloat *params_base = (GLfloat *) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLfloat *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexLevelParameterfv(
+        (GLenum)target,
+        (GLint)level,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetTexLevelParameterfv ( GLenum target, GLint level, GLenum pname, GLfloat *params ) */
+static void
+android_glGetTexLevelParameterfv__IIILjava_nio_FloatBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint level, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLfloat *params = (GLfloat *) 0;
+
+    params = (GLfloat *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLfloat *) (_paramsBase + _bufferOffset);
+    }
+    glGetTexLevelParameterfv(
+        (GLenum)target,
+        (GLint)level,
+        (GLenum)pname,
+        (GLfloat *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_TRUE);
+    }
+}
+
+/* void glBindVertexBuffer ( GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride ) */
+static void
+android_glBindVertexBuffer__IIJI
+  (JNIEnv *_env, jobject _this, jint bindingindex, jint buffer, jlong offset, jint stride) {
+    if (sizeof(GLintptr) != sizeof(jlong) && (offset < LONG_MIN || offset > LONG_MAX)) {
+        jniThrowException(_env, "java/lang/IllegalArgumentException", "offset too large");
+        return;
+    }
+    glBindVertexBuffer(
+        (GLuint)bindingindex,
+        (GLuint)buffer,
+        (GLintptr)offset,
+        (GLsizei)stride
+    );
+}
+/* void glVertexAttribFormat ( GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset ) */
+static void
+android_glVertexAttribFormat__IIIZI
+  (JNIEnv *_env, jobject _this, jint attribindex, jint size, jint type, jboolean normalized, jint relativeoffset) {
+    glVertexAttribFormat(
+        (GLuint)attribindex,
+        (GLint)size,
+        (GLenum)type,
+        (GLboolean)normalized,
+        (GLuint)relativeoffset
+    );
+}
+
+/* void glVertexAttribIFormat ( GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset ) */
+static void
+android_glVertexAttribIFormat__IIII
+  (JNIEnv *_env, jobject _this, jint attribindex, jint size, jint type, jint relativeoffset) {
+    glVertexAttribIFormat(
+        (GLuint)attribindex,
+        (GLint)size,
+        (GLenum)type,
+        (GLuint)relativeoffset
+    );
+}
+
+/* void glVertexAttribBinding ( GLuint attribindex, GLuint bindingindex ) */
+static void
+android_glVertexAttribBinding__II
+  (JNIEnv *_env, jobject _this, jint attribindex, jint bindingindex) {
+    glVertexAttribBinding(
+        (GLuint)attribindex,
+        (GLuint)bindingindex
+    );
+}
+
+/* void glVertexBindingDivisor ( GLuint bindingindex, GLuint divisor ) */
+static void
+android_glVertexBindingDivisor__II
+  (JNIEnv *_env, jobject _this, jint bindingindex, jint divisor) {
+    glVertexBindingDivisor(
+        (GLuint)bindingindex,
+        (GLuint)divisor
+    );
+}
+
+static const char *classPathName = "android/opengl/GLES31";
+
+static JNINativeMethod methods[] = {
+{"_nativeClassInit", "()V", (void*)nativeClassInit },
+{"glDispatchCompute", "(III)V", (void *) android_glDispatchCompute__III },
+{"glDispatchComputeIndirect", "(J)V", (void *) android_glDispatchComputeIndirect },
+{"glDrawArraysIndirect", "(IJ)V", (void *) android_glDrawArraysIndirect },
+{"glDrawElementsIndirect", "(IIJ)V", (void *) android_glDrawElementsIndirect },
+{"glFramebufferParameteri", "(III)V", (void *) android_glFramebufferParameteri__III },
+{"glGetFramebufferParameteriv", "(II[II)V", (void *) android_glGetFramebufferParameteriv__II_3II },
+{"glGetFramebufferParameteriv", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetFramebufferParameteriv__IILjava_nio_IntBuffer_2 },
+{"glGetProgramInterfaceiv", "(III[II)V", (void *) android_glGetProgramInterfaceiv__III_3II },
+{"glGetProgramInterfaceiv", "(IIILjava/nio/IntBuffer;)V", (void *) android_glGetProgramInterfaceiv__IIILjava_nio_IntBuffer_2 },
+{"glGetProgramResourceIndex", "(IILjava/lang/String;)I", (void *) android_glGetProgramResourceIndex__IILjava_lang_String_2 },
+{"glGetProgramResourceName", "(III)Ljava/lang/String;", (void *) android_glGetProgramResourceName },
+{"glGetProgramResourceiv", "(IIII[III[II[II)V", (void *) android_glGetProgramResourceiv__IIII_3III_3II_3II },
+{"glGetProgramResourceiv", "(IIIILjava/nio/IntBuffer;ILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)V", (void *) android_glGetProgramResourceiv__IIIILjava_nio_IntBuffer_2ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
+{"glGetProgramResourceLocation", "(IILjava/lang/String;)I", (void *) android_glGetProgramResourceLocation__IILjava_lang_String_2 },
+{"glUseProgramStages", "(III)V", (void *) android_glUseProgramStages__III },
+{"glActiveShaderProgram", "(II)V", (void *) android_glActiveShaderProgram__II },
+{"glCreateShaderProgramv", "(I[Ljava/lang/String;)I", (void *) android_glCreateShaderProgramv },
+{"glBindProgramPipeline", "(I)V", (void *) android_glBindProgramPipeline__I },
+{"glDeleteProgramPipelines", "(I[II)V", (void *) android_glDeleteProgramPipelines__I_3II },
+{"glDeleteProgramPipelines", "(ILjava/nio/IntBuffer;)V", (void *) android_glDeleteProgramPipelines__ILjava_nio_IntBuffer_2 },
+{"glGenProgramPipelines", "(I[II)V", (void *) android_glGenProgramPipelines__I_3II },
+{"glGenProgramPipelines", "(ILjava/nio/IntBuffer;)V", (void *) android_glGenProgramPipelines__ILjava_nio_IntBuffer_2 },
+{"glIsProgramPipeline", "(I)Z", (void *) android_glIsProgramPipeline__I },
+{"glGetProgramPipelineiv", "(II[II)V", (void *) android_glGetProgramPipelineiv__II_3II },
+{"glGetProgramPipelineiv", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetProgramPipelineiv__IILjava_nio_IntBuffer_2 },
+{"glProgramUniform1i", "(III)V", (void *) android_glProgramUniform1i__III },
+{"glProgramUniform2i", "(IIII)V", (void *) android_glProgramUniform2i__IIII },
+{"glProgramUniform3i", "(IIIII)V", (void *) android_glProgramUniform3i__IIIII },
+{"glProgramUniform4i", "(IIIIII)V", (void *) android_glProgramUniform4i__IIIIII },
+{"glProgramUniform1ui", "(III)V", (void *) android_glProgramUniform1ui__III },
+{"glProgramUniform2ui", "(IIII)V", (void *) android_glProgramUniform2ui__IIII },
+{"glProgramUniform3ui", "(IIIII)V", (void *) android_glProgramUniform3ui__IIIII },
+{"glProgramUniform4ui", "(IIIIII)V", (void *) android_glProgramUniform4ui__IIIIII },
+{"glProgramUniform1f", "(IIF)V", (void *) android_glProgramUniform1f__IIF },
+{"glProgramUniform2f", "(IIFF)V", (void *) android_glProgramUniform2f__IIFF },
+{"glProgramUniform3f", "(IIFFF)V", (void *) android_glProgramUniform3f__IIFFF },
+{"glProgramUniform4f", "(IIFFFF)V", (void *) android_glProgramUniform4f__IIFFFF },
+{"glProgramUniform1iv", "(III[II)V", (void *) android_glProgramUniform1iv__III_3II },
+{"glProgramUniform1iv", "(IIILjava/nio/IntBuffer;)V", (void *) android_glProgramUniform1iv__IIILjava_nio_IntBuffer_2 },
+{"glProgramUniform2iv", "(III[II)V", (void *) android_glProgramUniform2iv__III_3II },
+{"glProgramUniform2iv", "(IIILjava/nio/IntBuffer;)V", (void *) android_glProgramUniform2iv__IIILjava_nio_IntBuffer_2 },
+{"glProgramUniform3iv", "(III[II)V", (void *) android_glProgramUniform3iv__III_3II },
+{"glProgramUniform3iv", "(IIILjava/nio/IntBuffer;)V", (void *) android_glProgramUniform3iv__IIILjava_nio_IntBuffer_2 },
+{"glProgramUniform4iv", "(III[II)V", (void *) android_glProgramUniform4iv__III_3II },
+{"glProgramUniform4iv", "(IIILjava/nio/IntBuffer;)V", (void *) android_glProgramUniform4iv__IIILjava_nio_IntBuffer_2 },
+{"glProgramUniform1uiv", "(III[II)V", (void *) android_glProgramUniform1uiv__III_3II },
+{"glProgramUniform1uiv", "(IIILjava/nio/IntBuffer;)V", (void *) android_glProgramUniform1uiv__IIILjava_nio_IntBuffer_2 },
+{"glProgramUniform2uiv", "(III[II)V", (void *) android_glProgramUniform2uiv__III_3II },
+{"glProgramUniform2uiv", "(IIILjava/nio/IntBuffer;)V", (void *) android_glProgramUniform2uiv__IIILjava_nio_IntBuffer_2 },
+{"glProgramUniform3uiv", "(III[II)V", (void *) android_glProgramUniform3uiv__III_3II },
+{"glProgramUniform3uiv", "(IIILjava/nio/IntBuffer;)V", (void *) android_glProgramUniform3uiv__IIILjava_nio_IntBuffer_2 },
+{"glProgramUniform4uiv", "(III[II)V", (void *) android_glProgramUniform4uiv__III_3II },
+{"glProgramUniform4uiv", "(IIILjava/nio/IntBuffer;)V", (void *) android_glProgramUniform4uiv__IIILjava_nio_IntBuffer_2 },
+{"glProgramUniform1fv", "(III[FI)V", (void *) android_glProgramUniform1fv__III_3FI },
+{"glProgramUniform1fv", "(IIILjava/nio/FloatBuffer;)V", (void *) android_glProgramUniform1fv__IIILjava_nio_FloatBuffer_2 },
+{"glProgramUniform2fv", "(III[FI)V", (void *) android_glProgramUniform2fv__III_3FI },
+{"glProgramUniform2fv", "(IIILjava/nio/FloatBuffer;)V", (void *) android_glProgramUniform2fv__IIILjava_nio_FloatBuffer_2 },
+{"glProgramUniform3fv", "(III[FI)V", (void *) android_glProgramUniform3fv__III_3FI },
+{"glProgramUniform3fv", "(IIILjava/nio/FloatBuffer;)V", (void *) android_glProgramUniform3fv__IIILjava_nio_FloatBuffer_2 },
+{"glProgramUniform4fv", "(III[FI)V", (void *) android_glProgramUniform4fv__III_3FI },
+{"glProgramUniform4fv", "(IIILjava/nio/FloatBuffer;)V", (void *) android_glProgramUniform4fv__IIILjava_nio_FloatBuffer_2 },
+{"glProgramUniformMatrix2fv", "(IIIZ[FI)V", (void *) android_glProgramUniformMatrix2fv__IIIZ_3FI },
+{"glProgramUniformMatrix2fv", "(IIIZLjava/nio/FloatBuffer;)V", (void *) android_glProgramUniformMatrix2fv__IIIZLjava_nio_FloatBuffer_2 },
+{"glProgramUniformMatrix3fv", "(IIIZ[FI)V", (void *) android_glProgramUniformMatrix3fv__IIIZ_3FI },
+{"glProgramUniformMatrix3fv", "(IIIZLjava/nio/FloatBuffer;)V", (void *) android_glProgramUniformMatrix3fv__IIIZLjava_nio_FloatBuffer_2 },
+{"glProgramUniformMatrix4fv", "(IIIZ[FI)V", (void *) android_glProgramUniformMatrix4fv__IIIZ_3FI },
+{"glProgramUniformMatrix4fv", "(IIIZLjava/nio/FloatBuffer;)V", (void *) android_glProgramUniformMatrix4fv__IIIZLjava_nio_FloatBuffer_2 },
+{"glProgramUniformMatrix2x3fv", "(IIIZ[FI)V", (void *) android_glProgramUniformMatrix2x3fv__IIIZ_3FI },
+{"glProgramUniformMatrix2x3fv", "(IIIZLjava/nio/FloatBuffer;)V", (void *) android_glProgramUniformMatrix2x3fv__IIIZLjava_nio_FloatBuffer_2 },
+{"glProgramUniformMatrix3x2fv", "(IIIZ[FI)V", (void *) android_glProgramUniformMatrix3x2fv__IIIZ_3FI },
+{"glProgramUniformMatrix3x2fv", "(IIIZLjava/nio/FloatBuffer;)V", (void *) android_glProgramUniformMatrix3x2fv__IIIZLjava_nio_FloatBuffer_2 },
+{"glProgramUniformMatrix2x4fv", "(IIIZ[FI)V", (void *) android_glProgramUniformMatrix2x4fv__IIIZ_3FI },
+{"glProgramUniformMatrix2x4fv", "(IIIZLjava/nio/FloatBuffer;)V", (void *) android_glProgramUniformMatrix2x4fv__IIIZLjava_nio_FloatBuffer_2 },
+{"glProgramUniformMatrix4x2fv", "(IIIZ[FI)V", (void *) android_glProgramUniformMatrix4x2fv__IIIZ_3FI },
+{"glProgramUniformMatrix4x2fv", "(IIIZLjava/nio/FloatBuffer;)V", (void *) android_glProgramUniformMatrix4x2fv__IIIZLjava_nio_FloatBuffer_2 },
+{"glProgramUniformMatrix3x4fv", "(IIIZ[FI)V", (void *) android_glProgramUniformMatrix3x4fv__IIIZ_3FI },
+{"glProgramUniformMatrix3x4fv", "(IIIZLjava/nio/FloatBuffer;)V", (void *) android_glProgramUniformMatrix3x4fv__IIIZLjava_nio_FloatBuffer_2 },
+{"glProgramUniformMatrix4x3fv", "(IIIZ[FI)V", (void *) android_glProgramUniformMatrix4x3fv__IIIZ_3FI },
+{"glProgramUniformMatrix4x3fv", "(IIIZLjava/nio/FloatBuffer;)V", (void *) android_glProgramUniformMatrix4x3fv__IIIZLjava_nio_FloatBuffer_2 },
+{"glValidateProgramPipeline", "(I)V", (void *) android_glValidateProgramPipeline__I },
+{"glGetProgramPipelineInfoLog", "(I)Ljava/lang/String;", (void *) android_glGetProgramPipelineInfoLog },
+{"glBindImageTexture", "(IIIZIII)V", (void *) android_glBindImageTexture__IIIZIII },
+{"glGetBooleani_v", "(II[ZI)V", (void *) android_glGetBooleani_v__II_3ZI },
+{"glGetBooleani_v", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetBooleani_v__IILjava_nio_IntBuffer_2 },
+{"glMemoryBarrier", "(I)V", (void *) android_glMemoryBarrier__I },
+{"glMemoryBarrierByRegion", "(I)V", (void *) android_glMemoryBarrierByRegion__I },
+{"glTexStorage2DMultisample", "(IIIIIZ)V", (void *) android_glTexStorage2DMultisample__IIIIIZ },
+{"glGetMultisamplefv", "(II[FI)V", (void *) android_glGetMultisamplefv__II_3FI },
+{"glGetMultisamplefv", "(IILjava/nio/FloatBuffer;)V", (void *) android_glGetMultisamplefv__IILjava_nio_FloatBuffer_2 },
+{"glSampleMaski", "(II)V", (void *) android_glSampleMaski__II },
+{"glGetTexLevelParameteriv", "(III[II)V", (void *) android_glGetTexLevelParameteriv__III_3II },
+{"glGetTexLevelParameteriv", "(IIILjava/nio/IntBuffer;)V", (void *) android_glGetTexLevelParameteriv__IIILjava_nio_IntBuffer_2 },
+{"glGetTexLevelParameterfv", "(III[FI)V", (void *) android_glGetTexLevelParameterfv__III_3FI },
+{"glGetTexLevelParameterfv", "(IIILjava/nio/FloatBuffer;)V", (void *) android_glGetTexLevelParameterfv__IIILjava_nio_FloatBuffer_2 },
+{"glBindVertexBuffer", "(IIJI)V", (void *) android_glBindVertexBuffer__IIJI },
+{"glVertexAttribFormat", "(IIIZI)V", (void *) android_glVertexAttribFormat__IIIZI },
+{"glVertexAttribIFormat", "(IIII)V", (void *) android_glVertexAttribIFormat__IIII },
+{"glVertexAttribBinding", "(II)V", (void *) android_glVertexAttribBinding__II },
+{"glVertexBindingDivisor", "(II)V", (void *) android_glVertexBindingDivisor__II },
+};
+
+int register_android_opengl_jni_GLES31(JNIEnv *_env)
+{
+    int err;
+    err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));
+    return err;
+}
diff --git a/core/jni/android_opengl_GLES31Ext.cpp b/core/jni/android_opengl_GLES31Ext.cpp
new file mode 100644
index 0000000..d76c166
--- /dev/null
+++ b/core/jni/android_opengl_GLES31Ext.cpp
@@ -0,0 +1,1385 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This source file is automatically generated
+
+#include <GLES3/gl31.h>
+#include <GLES2/gl2ext.h>
+
+#include <jni.h>
+#include <JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <utils/misc.h>
+#include <assert.h>
+
+static int initialized = 0;
+
+static jclass nioAccessClass;
+static jclass bufferClass;
+static jmethodID getBasePointerID;
+static jmethodID getBaseArrayID;
+static jmethodID getBaseArrayOffsetID;
+static jfieldID positionID;
+static jfieldID limitID;
+static jfieldID elementSizeShiftID;
+
+
+/* special calls implemented in Android's GLES wrapper used to more
+ * efficiently bound-check passed arrays */
+extern "C" {
+#ifdef GL_VERSION_ES_CM_1_1
+GL_API void GL_APIENTRY glColorPointerBounds(GLint size, GLenum type, GLsizei stride,
+        const GLvoid *ptr, GLsizei count);
+GL_API void GL_APIENTRY glNormalPointerBounds(GLenum type, GLsizei stride,
+        const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glTexCoordPointerBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glVertexPointerBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glPointSizePointerOESBounds(GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glMatrixIndexPointerOESBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count);
+#endif
+#ifdef GL_ES_VERSION_2_0
+static void glVertexAttribPointerBounds(GLuint indx, GLint size, GLenum type,
+        GLboolean normalized, GLsizei stride, const GLvoid *pointer, GLsizei count) {
+    glVertexAttribPointer(indx, size, type, normalized, stride, pointer);
+}
+#endif
+#ifdef GL_ES_VERSION_3_0
+static void glVertexAttribIPointerBounds(GLuint indx, GLint size, GLenum type,
+        GLsizei stride, const GLvoid *pointer, GLsizei count) {
+    glVertexAttribIPointer(indx, size, type, stride, pointer);
+}
+#endif
+}
+
+/* Cache method IDs each time the class is loaded. */
+
+static void
+nativeClassInit(JNIEnv *_env, jclass glImplClass)
+{
+    jclass nioAccessClassLocal = _env->FindClass("java/nio/NIOAccess");
+    nioAccessClass = (jclass) _env->NewGlobalRef(nioAccessClassLocal);
+
+    jclass bufferClassLocal = _env->FindClass("java/nio/Buffer");
+    bufferClass = (jclass) _env->NewGlobalRef(bufferClassLocal);
+
+    getBasePointerID = _env->GetStaticMethodID(nioAccessClass,
+            "getBasePointer", "(Ljava/nio/Buffer;)J");
+    getBaseArrayID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
+    getBaseArrayOffsetID = _env->GetStaticMethodID(nioAccessClass,
+            "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
+
+    positionID = _env->GetFieldID(bufferClass, "position", "I");
+    limitID = _env->GetFieldID(bufferClass, "limit", "I");
+    elementSizeShiftID =
+        _env->GetFieldID(bufferClass, "_elementSizeShift", "I");
+}
+
+static void *
+getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *offset)
+{
+    jint position;
+    jint limit;
+    jint elementSizeShift;
+    jlong pointer;
+
+    position = _env->GetIntField(buffer, positionID);
+    limit = _env->GetIntField(buffer, limitID);
+    elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+    *remaining = (limit - position) << elementSizeShift;
+    pointer = _env->CallStaticLongMethod(nioAccessClass,
+            getBasePointerID, buffer);
+    if (pointer != 0L) {
+        *array = NULL;
+        return reinterpret_cast<void*>(pointer);
+    }
+
+    *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
+            getBaseArrayID, buffer);
+    *offset = _env->CallStaticIntMethod(nioAccessClass,
+            getBaseArrayOffsetID, buffer);
+
+    return NULL;
+}
+
+static void
+releasePointer(JNIEnv *_env, jarray array, void *data, jboolean commit)
+{
+    _env->ReleasePrimitiveArrayCritical(array, data,
+                       commit ? 0 : JNI_ABORT);
+}
+
+static void *
+getDirectBufferPointer(JNIEnv *_env, jobject buffer) {
+    char* buf = (char*) _env->GetDirectBufferAddress(buffer);
+    if (buf) {
+        jint position = _env->GetIntField(buffer, positionID);
+        jint elementSizeShift = _env->GetIntField(buffer, elementSizeShiftID);
+        buf += position << elementSizeShift;
+    } else {
+        jniThrowException(_env, "java/lang/IllegalArgumentException",
+                          "Must use a native order direct Buffer");
+    }
+    return (void*) buf;
+}
+
+// --------------------------------------------------------------------------
+
+/*
+ * returns the number of values glGet returns for a given pname.
+ *
+ * The code below is written such that pnames requiring only one values
+ * are the default (and are not explicitely tested for). This makes the
+ * checking code much shorter/readable/efficient.
+ *
+ * This means that unknown pnames (e.g.: extensions) will default to 1. If
+ * that unknown pname needs more than 1 value, then the validation check
+ * is incomplete and the app may crash if it passed the wrong number params.
+ */
+static int getNeededCount(GLint pname) {
+    int needed = 1;
+#ifdef GL_ES_VERSION_2_0
+    // GLES 2.x pnames
+    switch (pname) {
+        case GL_ALIASED_LINE_WIDTH_RANGE:
+        case GL_ALIASED_POINT_SIZE_RANGE:
+            needed = 2;
+            break;
+
+        case GL_BLEND_COLOR:
+        case GL_COLOR_CLEAR_VALUE:
+        case GL_COLOR_WRITEMASK:
+        case GL_SCISSOR_BOX:
+        case GL_VIEWPORT:
+            needed = 4;
+            break;
+
+        case GL_COMPRESSED_TEXTURE_FORMATS:
+            glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &needed);
+            break;
+
+        case GL_SHADER_BINARY_FORMATS:
+            glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &needed);
+            break;
+    }
+#endif
+
+#ifdef GL_VERSION_ES_CM_1_1
+    // GLES 1.x pnames
+    switch (pname) {
+        case GL_ALIASED_LINE_WIDTH_RANGE:
+        case GL_ALIASED_POINT_SIZE_RANGE:
+        case GL_DEPTH_RANGE:
+        case GL_SMOOTH_LINE_WIDTH_RANGE:
+        case GL_SMOOTH_POINT_SIZE_RANGE:
+            needed = 2;
+            break;
+
+        case GL_CURRENT_NORMAL:
+        case GL_POINT_DISTANCE_ATTENUATION:
+            needed = 3;
+            break;
+
+        case GL_COLOR_CLEAR_VALUE:
+        case GL_COLOR_WRITEMASK:
+        case GL_CURRENT_COLOR:
+        case GL_CURRENT_TEXTURE_COORDS:
+        case GL_FOG_COLOR:
+        case GL_LIGHT_MODEL_AMBIENT:
+        case GL_SCISSOR_BOX:
+        case GL_VIEWPORT:
+            needed = 4;
+            break;
+
+        case GL_MODELVIEW_MATRIX:
+        case GL_PROJECTION_MATRIX:
+        case GL_TEXTURE_MATRIX:
+            needed = 16;
+            break;
+
+        case GL_COMPRESSED_TEXTURE_FORMATS:
+            glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &needed);
+            break;
+    }
+#endif
+    return needed;
+}
+
+template <typename JTYPEARRAY, typename CTYPE, void GET(GLenum, CTYPE*)>
+static void
+get
+  (JNIEnv *_env, jobject _this, jint pname, JTYPEARRAY params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    CTYPE *params_base = (CTYPE *) 0;
+    jint _remaining;
+    CTYPE *params = (CTYPE *) 0;
+    int _needed = 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    _needed = getNeededCount(pname);
+    // if we didn't find this pname, we just assume the user passed
+    // an array of the right size -- this might happen with extensions
+    // or if we forget an enum here.
+    if (_remaining < _needed) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "length - offset < needed";
+        goto exit;
+    }
+    params_base = (CTYPE *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    GET(
+        (GLenum)pname,
+        (CTYPE *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+
+template <typename CTYPE, void GET(GLenum, CTYPE*)>
+static void
+getarray
+  (JNIEnv *_env, jobject _this, jint pname, jobject params_buf) {
+    jint _exception = 0;
+    const char * _exceptionType;
+    const char * _exceptionMessage;
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    CTYPE *params = (CTYPE *) 0;
+    int _needed = 0;
+
+    params = (CTYPE *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    _remaining /= sizeof(CTYPE);    // convert from bytes to item count
+    _needed = getNeededCount(pname);
+    // if we didn't find this pname, we just assume the user passed
+    // an array of the right size -- this might happen with extensions
+    // or if we forget an enum here.
+    if (_needed>0 && _remaining < _needed) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "remaining() < needed";
+        goto exit;
+    }
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (CTYPE *) (_paramsBase + _bufferOffset);
+    }
+    GET(
+        (GLenum)pname,
+        (CTYPE *)params
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, params, _exception ? JNI_FALSE : JNI_TRUE);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+// --------------------------------------------------------------------------
+/* void glBlendBarrierKHR ( void ) */
+static void
+android_glBlendBarrierKHR__
+  (JNIEnv *_env, jobject _this) {
+    glBlendBarrierKHR();
+}
+
+/* void glDebugMessageControlKHR ( GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled ) */
+static void
+android_glDebugMessageControlKHR__IIII_3IIZ
+  (JNIEnv *_env, jobject _this, jint source, jint type, jint severity, jint count, jintArray ids_ref, jint offset, jboolean enabled) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint *ids_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *ids = (GLuint *) 0;
+
+    if (!ids_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "ids == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(ids_ref) - offset;
+    ids_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(ids_ref, (jboolean *)0);
+    ids = ids_base + offset;
+
+    glDebugMessageControlKHR(
+        (GLenum)source,
+        (GLenum)type,
+        (GLenum)severity,
+        (GLsizei)count,
+        (GLuint *)ids,
+        (GLboolean)enabled
+    );
+
+exit:
+    if (ids_base) {
+        _env->ReleasePrimitiveArrayCritical(ids_ref, ids_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glDebugMessageControlKHR ( GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled ) */
+static void
+android_glDebugMessageControlKHR__IIIILjava_nio_IntBuffer_2Z
+  (JNIEnv *_env, jobject _this, jint source, jint type, jint severity, jint count, jobject ids_buf, jboolean enabled) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLuint *ids = (GLuint *) 0;
+
+    ids = (GLuint *)getPointer(_env, ids_buf, &_array, &_remaining, &_bufferOffset);
+    if (ids == NULL) {
+        char * _idsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        ids = (GLuint *) (_idsBase + _bufferOffset);
+    }
+    glDebugMessageControlKHR(
+        (GLenum)source,
+        (GLenum)type,
+        (GLenum)severity,
+        (GLsizei)count,
+        (GLuint *)ids,
+        (GLboolean)enabled
+    );
+    if (_array) {
+        releasePointer(_env, _array, ids, JNI_FALSE);
+    }
+}
+
+/* void glDebugMessageInsertKHR ( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf ) */
+static void
+android_glDebugMessageInsertKHR__IIIILjava_lang_String_2
+  (JNIEnv *_env, jobject _this, jint source, jint type, jint id, jint severity, jstring buf) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    const char* _nativebuf = 0;
+    jint _length = 0;
+
+    if (!buf) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "buf == null";
+        goto exit;
+    }
+    _nativebuf = _env->GetStringUTFChars(buf, 0);
+    _length = _env->GetStringUTFLength(buf);
+
+    glDebugMessageInsertKHR(
+        (GLenum)source,
+        (GLenum)type,
+        (GLuint)id,
+        (GLenum)severity,
+        (GLsizei)_length,
+        (GLchar *)_nativebuf
+    );
+
+exit:
+    if (_nativebuf) {
+        _env->ReleaseStringUTFChars(buf, _nativebuf);
+    }
+
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glDebugMessageCallbackKHR ( GLDEBUGPROCKHR callback, const void *userParam ) */
+static void
+android_glDebugMessageCallbackKHR(JNIEnv *_env, jobject _this, jobject callback) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+}
+/* GLuint glGetDebugMessageLogKHR ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog ) */
+static jint
+android_glGetDebugMessageLogKHR__II_3II_3II_3II_3II_3II_3BI
+  (JNIEnv *_env, jobject _this, jint count, jint bufSize, jintArray sources_ref, jint sourcesOffset, jintArray types_ref, jint typesOffset, jintArray ids_ref, jint idsOffset, jintArray severities_ref, jint severitiesOffset, jintArray lengths_ref, jint lengthsOffset, jbyteArray messageLog_ref, jint messageLogOffset) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return 0;
+}
+
+/* GLuint glGetDebugMessageLogKHR ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog ) */
+static uint
+android_glGetDebugMessageLogKHR__ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2
+  (JNIEnv *_env, jobject _this, jint count, jobject sources_ref, jobject types_ref, jobject ids_ref, jobject severities_ref, jobject lengths_ref, jobject messageLog_ref) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return 0;
+}
+
+/* GLuint glGetDebugMessageLogKHR ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog ) */
+static jobjectArray
+android_glGetDebugMessageLogKHR__I_3II_3II_3II_3II
+  (JNIEnv *_env, jobject _this, jint count, jintArray sources_ref, jint sourcesOffset, jintArray types_ref, jint typesOffset, jintArray ids_ref, jint idsOffset, jintArray severities_ref, jint severitiesOffset) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return 0;
+}
+
+/* GLuint glGetDebugMessageLogKHR ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog ) */
+static jobjectArray
+android_glGetDebugMessageLogKHR__ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint count, jobject sources_ref, jobject types_ref, jobject ids_ref, jobject severities_ref) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return 0;
+}
+/* void glPushDebugGroupKHR ( GLenum source, GLuint id, GLsizei length, const GLchar *message ) */
+static void
+android_glPushDebugGroupKHR__IIILjava_lang_String_2
+  (JNIEnv *_env, jobject _this, jint source, jint id, jint length, jstring message) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    const char* _nativemessage = 0;
+
+    if (!message) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "message == null";
+        goto exit;
+    }
+    _nativemessage = _env->GetStringUTFChars(message, 0);
+
+    glPushDebugGroupKHR(
+        (GLenum)source,
+        (GLuint)id,
+        (GLsizei)length,
+        (GLchar *)_nativemessage
+    );
+
+exit:
+    if (_nativemessage) {
+        _env->ReleaseStringUTFChars(message, _nativemessage);
+    }
+
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glPopDebugGroupKHR ( void ) */
+static void
+android_glPopDebugGroupKHR__
+  (JNIEnv *_env, jobject _this) {
+    glPopDebugGroupKHR();
+}
+
+/* void glObjectLabelKHR ( GLenum identifier, GLuint name, GLsizei length, const GLchar *label ) */
+static void
+android_glObjectLabelKHR__IIILjava_lang_String_2
+  (JNIEnv *_env, jobject _this, jint identifier, jint name, jint length, jstring label) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    const char* _nativelabel = 0;
+
+    if (!label) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "label == null";
+        goto exit;
+    }
+    _nativelabel = _env->GetStringUTFChars(label, 0);
+
+    glObjectLabelKHR(
+        (GLenum)identifier,
+        (GLuint)name,
+        (GLsizei)length,
+        (GLchar *)_nativelabel
+    );
+
+exit:
+    if (_nativelabel) {
+        _env->ReleaseStringUTFChars(label, _nativelabel);
+    }
+
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetObjectLabelKHR ( GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label ) */
+static jstring
+android_glGetObjectLabelKHR(JNIEnv *_env, jobject _this, jint identifier, jint name) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return NULL;
+}
+
+/* void glObjectPtrLabelKHR ( const void *ptr, GLsizei length, const GLchar *label ) */
+static void
+android_glObjectPtrLabelKHR(JNIEnv *_env, jobject _this, jlong ptr, jstring label) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+}
+
+/* void glGetObjectPtrLabelKHR ( const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label ) */
+static jstring
+android_glGetObjectPtrLabelKHR(JNIEnv *_env, jobject _this, jlong ptr) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return NULL;
+}
+
+/* void glGetPointervKHR ( GLenum pname, void **params ) */
+static jobject
+android_glGetDebugMessageCallbackKHR(JNIEnv *_env, jobject _this) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return NULL;
+}
+
+/* void glMinSampleShadingOES ( GLfloat value ) */
+static void
+android_glMinSampleShadingOES__F
+  (JNIEnv *_env, jobject _this, jfloat value) {
+    glMinSampleShadingOES(
+        (GLfloat)value
+    );
+}
+
+/* void glTexStorage3DMultisampleOES ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations ) */
+static void
+android_glTexStorage3DMultisampleOES__IIIIIIZ
+  (JNIEnv *_env, jobject _this, jint target, jint samples, jint internalformat, jint width, jint height, jint depth, jboolean fixedsamplelocations) {
+    glTexStorage3DMultisampleOES(
+        (GLenum)target,
+        (GLsizei)samples,
+        (GLenum)internalformat,
+        (GLsizei)width,
+        (GLsizei)height,
+        (GLsizei)depth,
+        (GLboolean)fixedsamplelocations
+    );
+}
+
+/* void glCopyImageSubDataEXT ( GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth ) */
+static void
+android_glCopyImageSubDataEXT__IIIIIIIIIIIIIII
+  (JNIEnv *_env, jobject _this, jint srcName, jint srcTarget, jint srcLevel, jint srcX, jint srcY, jint srcZ, jint dstName, jint dstTarget, jint dstLevel, jint dstX, jint dstY, jint dstZ, jint srcWidth, jint srcHeight, jint srcDepth) {
+    glCopyImageSubDataEXT(
+        (GLuint)srcName,
+        (GLenum)srcTarget,
+        (GLint)srcLevel,
+        (GLint)srcX,
+        (GLint)srcY,
+        (GLint)srcZ,
+        (GLuint)dstName,
+        (GLenum)dstTarget,
+        (GLint)dstLevel,
+        (GLint)dstX,
+        (GLint)dstY,
+        (GLint)dstZ,
+        (GLsizei)srcWidth,
+        (GLsizei)srcHeight,
+        (GLsizei)srcDepth
+    );
+}
+
+/* void glEnableiEXT ( GLenum target, GLuint index ) */
+static void
+android_glEnableiEXT__II
+  (JNIEnv *_env, jobject _this, jint target, jint index) {
+    glEnableiEXT(
+        (GLenum)target,
+        (GLuint)index
+    );
+}
+
+/* void glDisableiEXT ( GLenum target, GLuint index ) */
+static void
+android_glDisableiEXT__II
+  (JNIEnv *_env, jobject _this, jint target, jint index) {
+    glDisableiEXT(
+        (GLenum)target,
+        (GLuint)index
+    );
+}
+
+/* void glBlendEquationiEXT ( GLuint buf, GLenum mode ) */
+static void
+android_glBlendEquationiEXT__II
+  (JNIEnv *_env, jobject _this, jint buf, jint mode) {
+    glBlendEquationiEXT(
+        (GLuint)buf,
+        (GLenum)mode
+    );
+}
+
+/* void glBlendEquationSeparateiEXT ( GLuint buf, GLenum modeRGB, GLenum modeAlpha ) */
+static void
+android_glBlendEquationSeparateiEXT__III
+  (JNIEnv *_env, jobject _this, jint buf, jint modeRGB, jint modeAlpha) {
+    glBlendEquationSeparateiEXT(
+        (GLuint)buf,
+        (GLenum)modeRGB,
+        (GLenum)modeAlpha
+    );
+}
+
+/* void glBlendFunciEXT ( GLuint buf, GLenum src, GLenum dst ) */
+static void
+android_glBlendFunciEXT__III
+  (JNIEnv *_env, jobject _this, jint buf, jint src, jint dst) {
+    glBlendFunciEXT(
+        (GLuint)buf,
+        (GLenum)src,
+        (GLenum)dst
+    );
+}
+
+/* void glBlendFuncSeparateiEXT ( GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha ) */
+static void
+android_glBlendFuncSeparateiEXT__IIIII
+  (JNIEnv *_env, jobject _this, jint buf, jint srcRGB, jint dstRGB, jint srcAlpha, jint dstAlpha) {
+    glBlendFuncSeparateiEXT(
+        (GLuint)buf,
+        (GLenum)srcRGB,
+        (GLenum)dstRGB,
+        (GLenum)srcAlpha,
+        (GLenum)dstAlpha
+    );
+}
+
+/* void glColorMaskiEXT ( GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a ) */
+static void
+android_glColorMaskiEXT__IZZZZ
+  (JNIEnv *_env, jobject _this, jint index, jboolean r, jboolean g, jboolean b, jboolean a) {
+    glColorMaskiEXT(
+        (GLuint)index,
+        (GLboolean)r,
+        (GLboolean)g,
+        (GLboolean)b,
+        (GLboolean)a
+    );
+}
+
+/* GLboolean glIsEnablediEXT ( GLenum target, GLuint index ) */
+static jboolean
+android_glIsEnablediEXT__II
+  (JNIEnv *_env, jobject _this, jint target, jint index) {
+    GLboolean _returnValue;
+    _returnValue = glIsEnablediEXT(
+        (GLenum)target,
+        (GLuint)index
+    );
+    return (jboolean)_returnValue;
+}
+
+/* void glFramebufferTextureEXT ( GLenum target, GLenum attachment, GLuint texture, GLint level ) */
+static void
+android_glFramebufferTextureEXT__IIII
+  (JNIEnv *_env, jobject _this, jint target, jint attachment, jint texture, jint level) {
+    glFramebufferTextureEXT(
+        (GLenum)target,
+        (GLenum)attachment,
+        (GLuint)texture,
+        (GLint)level
+    );
+}
+
+/* void glPrimitiveBoundingBoxEXT ( GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW ) */
+static void
+android_glPrimitiveBoundingBoxEXT__FFFFFFFF
+  (JNIEnv *_env, jobject _this, jfloat minX, jfloat minY, jfloat minZ, jfloat minW, jfloat maxX, jfloat maxY, jfloat maxZ, jfloat maxW) {
+    glPrimitiveBoundingBoxEXT(
+        (GLfloat)minX,
+        (GLfloat)minY,
+        (GLfloat)minZ,
+        (GLfloat)minW,
+        (GLfloat)maxX,
+        (GLfloat)maxY,
+        (GLfloat)maxZ,
+        (GLfloat)maxW
+    );
+}
+
+/* void glPatchParameteriEXT ( GLenum pname, GLint value ) */
+static void
+android_glPatchParameteriEXT__II
+  (JNIEnv *_env, jobject _this, jint pname, jint value) {
+    glPatchParameteriEXT(
+        (GLenum)pname,
+        (GLint)value
+    );
+}
+
+/* void glTexParameterIivEXT ( GLenum target, GLenum pname, const GLint *params ) */
+static void
+android_glTexParameterIivEXT__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexParameterIivEXT(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glTexParameterIivEXT ( GLenum target, GLenum pname, const GLint *params ) */
+static void
+android_glTexParameterIivEXT__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
+    glTexParameterIivEXT(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glTexParameterIuivEXT ( GLenum target, GLenum pname, const GLuint *params ) */
+static void
+android_glTexParameterIuivEXT__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint *params_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *params = (GLuint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glTexParameterIuivEXT(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLuint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glTexParameterIuivEXT ( GLenum target, GLenum pname, const GLuint *params ) */
+static void
+android_glTexParameterIuivEXT__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLuint *params = (GLuint *) 0;
+
+    params = (GLuint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLuint *) (_paramsBase + _bufferOffset);
+    }
+    glTexParameterIuivEXT(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLuint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_FALSE);
+    }
+}
+
+/* void glGetTexParameterIivEXT ( GLenum target, GLenum pname, GLint *params ) */
+static void
+android_glGetTexParameterIivEXT__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexParameterIivEXT(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetTexParameterIivEXT ( GLenum target, GLenum pname, GLint *params ) */
+static void
+android_glGetTexParameterIivEXT__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
+    glGetTexParameterIivEXT(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_TRUE);
+    }
+}
+
+/* void glGetTexParameterIuivEXT ( GLenum target, GLenum pname, GLuint *params ) */
+static void
+android_glGetTexParameterIuivEXT__II_3II
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint *params_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *params = (GLuint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetTexParameterIuivEXT(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLuint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetTexParameterIuivEXT ( GLenum target, GLenum pname, GLuint *params ) */
+static void
+android_glGetTexParameterIuivEXT__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint target, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLuint *params = (GLuint *) 0;
+
+    params = (GLuint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLuint *) (_paramsBase + _bufferOffset);
+    }
+    glGetTexParameterIuivEXT(
+        (GLenum)target,
+        (GLenum)pname,
+        (GLuint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_TRUE);
+    }
+}
+
+/* void glSamplerParameterIivEXT ( GLuint sampler, GLenum pname, const GLint *param ) */
+static void
+android_glSamplerParameterIivEXT__II_3II
+  (JNIEnv *_env, jobject _this, jint sampler, jint pname, jintArray param_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *param_base = (GLint *) 0;
+    jint _remaining;
+    GLint *param = (GLint *) 0;
+
+    if (!param_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "param == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(param_ref) - offset;
+    param_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(param_ref, (jboolean *)0);
+    param = param_base + offset;
+
+    glSamplerParameterIivEXT(
+        (GLuint)sampler,
+        (GLenum)pname,
+        (GLint *)param
+    );
+
+exit:
+    if (param_base) {
+        _env->ReleasePrimitiveArrayCritical(param_ref, param_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glSamplerParameterIivEXT ( GLuint sampler, GLenum pname, const GLint *param ) */
+static void
+android_glSamplerParameterIivEXT__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *param = (GLint *) 0;
+
+    param = (GLint *)getPointer(_env, param_buf, &_array, &_remaining, &_bufferOffset);
+    if (param == NULL) {
+        char * _paramBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        param = (GLint *) (_paramBase + _bufferOffset);
+    }
+    glSamplerParameterIivEXT(
+        (GLuint)sampler,
+        (GLenum)pname,
+        (GLint *)param
+    );
+    if (_array) {
+        releasePointer(_env, _array, param, JNI_FALSE);
+    }
+}
+
+/* void glSamplerParameterIuivEXT ( GLuint sampler, GLenum pname, const GLuint *param ) */
+static void
+android_glSamplerParameterIuivEXT__II_3II
+  (JNIEnv *_env, jobject _this, jint sampler, jint pname, jintArray param_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint *param_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *param = (GLuint *) 0;
+
+    if (!param_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "param == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(param_ref) - offset;
+    param_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(param_ref, (jboolean *)0);
+    param = param_base + offset;
+
+    glSamplerParameterIuivEXT(
+        (GLuint)sampler,
+        (GLenum)pname,
+        (GLuint *)param
+    );
+
+exit:
+    if (param_base) {
+        _env->ReleasePrimitiveArrayCritical(param_ref, param_base,
+            JNI_ABORT);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glSamplerParameterIuivEXT ( GLuint sampler, GLenum pname, const GLuint *param ) */
+static void
+android_glSamplerParameterIuivEXT__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject param_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLuint *param = (GLuint *) 0;
+
+    param = (GLuint *)getPointer(_env, param_buf, &_array, &_remaining, &_bufferOffset);
+    if (param == NULL) {
+        char * _paramBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        param = (GLuint *) (_paramBase + _bufferOffset);
+    }
+    glSamplerParameterIuivEXT(
+        (GLuint)sampler,
+        (GLenum)pname,
+        (GLuint *)param
+    );
+    if (_array) {
+        releasePointer(_env, _array, param, JNI_FALSE);
+    }
+}
+
+/* void glGetSamplerParameterIivEXT ( GLuint sampler, GLenum pname, GLint *params ) */
+static void
+android_glGetSamplerParameterIivEXT__II_3II
+  (JNIEnv *_env, jobject _this, jint sampler, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLint *params_base = (GLint *) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetSamplerParameterIivEXT(
+        (GLuint)sampler,
+        (GLenum)pname,
+        (GLint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetSamplerParameterIivEXT ( GLuint sampler, GLenum pname, GLint *params ) */
+static void
+android_glGetSamplerParameterIivEXT__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLint *params = (GLint *) 0;
+
+    params = (GLint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLint *) (_paramsBase + _bufferOffset);
+    }
+    glGetSamplerParameterIivEXT(
+        (GLuint)sampler,
+        (GLenum)pname,
+        (GLint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_TRUE);
+    }
+}
+
+/* void glGetSamplerParameterIuivEXT ( GLuint sampler, GLenum pname, GLuint *params ) */
+static void
+android_glGetSamplerParameterIuivEXT__II_3II
+  (JNIEnv *_env, jobject _this, jint sampler, jint pname, jintArray params_ref, jint offset) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLuint *params_base = (GLuint *) 0;
+    jint _remaining;
+    GLuint *params = (GLuint *) 0;
+
+    if (!params_ref) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "params == null";
+        goto exit;
+    }
+    if (offset < 0) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "offset < 0";
+        goto exit;
+    }
+    _remaining = _env->GetArrayLength(params_ref) - offset;
+    params_base = (GLuint *)
+        _env->GetPrimitiveArrayCritical(params_ref, (jboolean *)0);
+    params = params_base + offset;
+
+    glGetSamplerParameterIuivEXT(
+        (GLuint)sampler,
+        (GLenum)pname,
+        (GLuint *)params
+    );
+
+exit:
+    if (params_base) {
+        _env->ReleasePrimitiveArrayCritical(params_ref, params_base,
+            _exception ? JNI_ABORT: 0);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+}
+
+/* void glGetSamplerParameterIuivEXT ( GLuint sampler, GLenum pname, GLuint *params ) */
+static void
+android_glGetSamplerParameterIuivEXT__IILjava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint sampler, jint pname, jobject params_buf) {
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    GLuint *params = (GLuint *) 0;
+
+    params = (GLuint *)getPointer(_env, params_buf, &_array, &_remaining, &_bufferOffset);
+    if (params == NULL) {
+        char * _paramsBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        params = (GLuint *) (_paramsBase + _bufferOffset);
+    }
+    glGetSamplerParameterIuivEXT(
+        (GLuint)sampler,
+        (GLenum)pname,
+        (GLuint *)params
+    );
+    if (_array) {
+        releasePointer(_env, _array, params, JNI_TRUE);
+    }
+}
+
+/* void glTexBufferEXT ( GLenum target, GLenum internalformat, GLuint buffer ) */
+static void
+android_glTexBufferEXT__III
+  (JNIEnv *_env, jobject _this, jint target, jint internalformat, jint buffer) {
+    glTexBufferEXT(
+        (GLenum)target,
+        (GLenum)internalformat,
+        (GLuint)buffer
+    );
+}
+
+/* void glTexBufferRangeEXT ( GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size ) */
+static void
+android_glTexBufferRangeEXT__IIIII
+  (JNIEnv *_env, jobject _this, jint target, jint internalformat, jint buffer, jint offset, jint size) {
+    glTexBufferRangeEXT(
+        (GLenum)target,
+        (GLenum)internalformat,
+        (GLuint)buffer,
+        (GLintptr)offset,
+        (GLsizeiptr)size
+    );
+}
+
+static const char *classPathName = "android/opengl/GLES31Ext";
+
+static JNINativeMethod methods[] = {
+{"_nativeClassInit", "()V", (void*)nativeClassInit },
+{"glBlendBarrierKHR", "()V", (void *) android_glBlendBarrierKHR__ },
+{"glDebugMessageControlKHR", "(IIII[IIZ)V", (void *) android_glDebugMessageControlKHR__IIII_3IIZ },
+{"glDebugMessageControlKHR", "(IIIILjava/nio/IntBuffer;Z)V", (void *) android_glDebugMessageControlKHR__IIIILjava_nio_IntBuffer_2Z },
+{"glDebugMessageInsertKHR", "(IIIILjava/lang/String;)V", (void *) android_glDebugMessageInsertKHR__IIIILjava_lang_String_2 },
+{"glDebugMessageCallbackKHR", "(Landroid/opengl/GLES31Ext$DebugProcKHR;)V", (void *) android_glDebugMessageCallbackKHR },
+{"glGetDebugMessageLogKHR", "(II[II[II[II[II[II[BI)I", (void *) android_glGetDebugMessageLogKHR__II_3II_3II_3II_3II_3II_3BI },
+{"glGetDebugMessageLogKHR", "(ILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/ByteBuffer;)I", (void *) android_glGetDebugMessageLogKHR__ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2 },
+{"glGetDebugMessageLogKHR", "(I[II[II[II[II)[Ljava/lang/String;", (void *) android_glGetDebugMessageLogKHR__I_3II_3II_3II_3II },
+{"glGetDebugMessageLogKHR", "(ILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;)[Ljava/lang/String;", (void *) android_glGetDebugMessageLogKHR__ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
+{"glPushDebugGroupKHR", "(IIILjava/lang/String;)V", (void *) android_glPushDebugGroupKHR__IIILjava_lang_String_2 },
+{"glPopDebugGroupKHR", "()V", (void *) android_glPopDebugGroupKHR__ },
+{"glObjectLabelKHR", "(IIILjava/lang/String;)V", (void *) android_glObjectLabelKHR__IIILjava_lang_String_2 },
+{"glGetObjectLabelKHR", "(II)Ljava/lang/String;", (void *) android_glGetObjectLabelKHR },
+{"glObjectPtrLabelKHR", "(JLjava/lang/String;)V", (void *) android_glObjectPtrLabelKHR },
+{"glGetObjectPtrLabelKHR", "(J)Ljava/lang/String;", (void *) android_glGetObjectPtrLabelKHR },
+{"glGetDebugMessageCallbackKHR", "()Landroid/opengl/GLES31Ext$DebugProcKHR;", (void *) android_glGetDebugMessageCallbackKHR },
+{"glMinSampleShadingOES", "(F)V", (void *) android_glMinSampleShadingOES__F },
+{"glTexStorage3DMultisampleOES", "(IIIIIIZ)V", (void *) android_glTexStorage3DMultisampleOES__IIIIIIZ },
+{"glCopyImageSubDataEXT", "(IIIIIIIIIIIIIII)V", (void *) android_glCopyImageSubDataEXT__IIIIIIIIIIIIIII },
+{"glEnableiEXT", "(II)V", (void *) android_glEnableiEXT__II },
+{"glDisableiEXT", "(II)V", (void *) android_glDisableiEXT__II },
+{"glBlendEquationiEXT", "(II)V", (void *) android_glBlendEquationiEXT__II },
+{"glBlendEquationSeparateiEXT", "(III)V", (void *) android_glBlendEquationSeparateiEXT__III },
+{"glBlendFunciEXT", "(III)V", (void *) android_glBlendFunciEXT__III },
+{"glBlendFuncSeparateiEXT", "(IIIII)V", (void *) android_glBlendFuncSeparateiEXT__IIIII },
+{"glColorMaskiEXT", "(IZZZZ)V", (void *) android_glColorMaskiEXT__IZZZZ },
+{"glIsEnablediEXT", "(II)Z", (void *) android_glIsEnablediEXT__II },
+{"glFramebufferTextureEXT", "(IIII)V", (void *) android_glFramebufferTextureEXT__IIII },
+{"glPrimitiveBoundingBoxEXT", "(FFFFFFFF)V", (void *) android_glPrimitiveBoundingBoxEXT__FFFFFFFF },
+{"glPatchParameteriEXT", "(II)V", (void *) android_glPatchParameteriEXT__II },
+{"glTexParameterIivEXT", "(II[II)V", (void *) android_glTexParameterIivEXT__II_3II },
+{"glTexParameterIivEXT", "(IILjava/nio/IntBuffer;)V", (void *) android_glTexParameterIivEXT__IILjava_nio_IntBuffer_2 },
+{"glTexParameterIuivEXT", "(II[II)V", (void *) android_glTexParameterIuivEXT__II_3II },
+{"glTexParameterIuivEXT", "(IILjava/nio/IntBuffer;)V", (void *) android_glTexParameterIuivEXT__IILjava_nio_IntBuffer_2 },
+{"glGetTexParameterIivEXT", "(II[II)V", (void *) android_glGetTexParameterIivEXT__II_3II },
+{"glGetTexParameterIivEXT", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetTexParameterIivEXT__IILjava_nio_IntBuffer_2 },
+{"glGetTexParameterIuivEXT", "(II[II)V", (void *) android_glGetTexParameterIuivEXT__II_3II },
+{"glGetTexParameterIuivEXT", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetTexParameterIuivEXT__IILjava_nio_IntBuffer_2 },
+{"glSamplerParameterIivEXT", "(II[II)V", (void *) android_glSamplerParameterIivEXT__II_3II },
+{"glSamplerParameterIivEXT", "(IILjava/nio/IntBuffer;)V", (void *) android_glSamplerParameterIivEXT__IILjava_nio_IntBuffer_2 },
+{"glSamplerParameterIuivEXT", "(II[II)V", (void *) android_glSamplerParameterIuivEXT__II_3II },
+{"glSamplerParameterIuivEXT", "(IILjava/nio/IntBuffer;)V", (void *) android_glSamplerParameterIuivEXT__IILjava_nio_IntBuffer_2 },
+{"glGetSamplerParameterIivEXT", "(II[II)V", (void *) android_glGetSamplerParameterIivEXT__II_3II },
+{"glGetSamplerParameterIivEXT", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetSamplerParameterIivEXT__IILjava_nio_IntBuffer_2 },
+{"glGetSamplerParameterIuivEXT", "(II[II)V", (void *) android_glGetSamplerParameterIuivEXT__II_3II },
+{"glGetSamplerParameterIuivEXT", "(IILjava/nio/IntBuffer;)V", (void *) android_glGetSamplerParameterIuivEXT__IILjava_nio_IntBuffer_2 },
+{"glTexBufferEXT", "(III)V", (void *) android_glTexBufferEXT__III },
+{"glTexBufferRangeEXT", "(IIIII)V", (void *) android_glTexBufferRangeEXT__IIIII },
+};
+
+int register_android_opengl_jni_GLES31Ext(JNIEnv *_env)
+{
+    int err;
+    err = android::AndroidRuntime::registerNativeMethods(_env, classPathName, methods, NELEM(methods));
+    return err;
+}
diff --git a/core/res/res/drawable/notification_quantum_media_progress.xml b/core/res/res/drawable/notification_quantum_media_progress.xml
new file mode 100644
index 0000000..74d871b
--- /dev/null
+++ b/core/res/res/drawable/notification_quantum_media_progress.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@id/background" android:drawable="@color/transparent">
+    </item>
+    <item android:id="@id/secondaryProgress">
+        <scale android:scaleWidth="100%"
+            android:drawable="@color/notification_media_progress" />
+    </item>
+    <item android:id="@id/progress">
+        <scale android:scaleWidth="100%"
+            android:drawable="@color/notification_media_progress" />
+    </item>
+</layer-list>
diff --git a/core/res/res/layout/notification_quantum_media_action.xml b/core/res/res/layout/notification_quantum_media_action.xml
new file mode 100644
index 0000000..17f0848
--- /dev/null
+++ b/core/res/res/layout/notification_quantum_media_action.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@android:style/Widget.Quantum.Light.Button.Borderless.Small"
+    android:id="@+id/action0"
+    android:layout_width="60dp"
+    android:layout_height="match_parent"
+    android:layout_weight="1"
+    android:gravity="center"
+    />
diff --git a/core/res/res/layout/notification_template_part_chronometer.xml b/core/res/res/layout/notification_template_part_chronometer.xml
index aa9c4dc..9b6e6c5 100644
--- a/core/res/res/layout/notification_template_part_chronometer.xml
+++ b/core/res/res/layout/notification_template_part_chronometer.xml
@@ -15,7 +15,7 @@
 -->
 
 <Chronometer android:id="@+id/chronometer" xmlns:android="http://schemas.android.com/apk/res/android"
-    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Time"
+    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Time"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center"
diff --git a/core/res/res/layout/notification_template_part_time.xml b/core/res/res/layout/notification_template_part_time.xml
index 2bd6c3f..b559dce 100644
--- a/core/res/res/layout/notification_template_part_time.xml
+++ b/core/res/res/layout/notification_template_part_time.xml
@@ -15,7 +15,7 @@
 -->
 
 <DateTimeView android:id="@+id/time" xmlns:android="http://schemas.android.com/apk/res/android"
-    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Time"
+    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Time"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center"
diff --git a/core/res/res/layout/notification_template_quantum_big_media.xml b/core/res/res/layout/notification_template_quantum_big_media.xml
new file mode 100644
index 0000000..5c9334e
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_big_media.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    internal:layout_minHeight="65dp"
+    internal:layout_maxHeight="unbounded"
+    >
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="fill_vertical"
+        android:minHeight="@dimen/notification_large_icon_height"
+        android:orientation="vertical"
+        android:gravity="top"
+        >
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingStart="@dimen/notification_large_icon_width"
+            android:minHeight="@dimen/notification_large_icon_height"
+            android:paddingTop="2dp"
+            android:orientation="vertical"
+            android:background="@color/notification_media_info_bg"
+            >
+            <LinearLayout
+                android:id="@+id/line1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="6dp"
+                android:layout_marginEnd="8dp"
+                android:layout_marginStart="8dp"
+                android:orientation="horizontal"
+                >
+                <TextView android:id="@+id/title"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    android:layout_weight="1"
+                    />
+                <ViewStub android:id="@+id/time"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_time"
+                    />
+                <ViewStub android:id="@+id/chronometer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_chronometer"
+                    />
+            </LinearLayout>
+            <TextView android:id="@+id/text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-2dp"
+                android:layout_marginBottom="-2dp"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="true"
+                android:fadingEdge="horizontal"
+                android:ellipsize="marquee"
+                android:visibility="gone"
+                />
+            <TextView android:id="@+id/big_text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:singleLine="false"
+                android:visibility="gone"
+                />
+            <LinearLayout
+                android:id="@+id/line3"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="8dp"
+                android:layout_marginEnd="8dp"
+                android:orientation="horizontal"
+                android:gravity="center_vertical"
+                >
+                <TextView android:id="@+id/text"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:layout_gravity="center"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    />
+                <TextView android:id="@+id/info"
+                    android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:singleLine="true"
+                    android:gravity="center"
+                    android:paddingStart="8dp"
+                    />
+            </LinearLayout>
+        </LinearLayout>
+        <FrameLayout
+                android:layout_width="match_parent"
+                android:layout_height="60dp"
+                android:id="@+id/media_action_area"
+                android:background="@color/notification_media_action_bg"
+                >
+            <LinearLayout
+                android:id="@+id/actions"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_marginTop="6dp"
+                android:orientation="horizontal"
+                >
+                <!-- media buttons will be added here -->
+            </LinearLayout>
+            <ProgressBar
+                android:id="@android:id/progress"
+                android:layout_width="match_parent"
+                android:layout_height="6dp"
+                android:layout_gravity="top"
+                android:visibility="gone"
+                style="@style/Widget.StatusBar.Quantum.ProgressBar"
+                />
+        </FrameLayout>
+    </LinearLayout>
+    <include layout="@layout/notification_template_icon_group"
+             android:layout_width="@dimen/notification_large_icon_width"
+             android:layout_height="@dimen/notification_large_icon_height"
+            />
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_quantum_media.xml b/core/res/res/layout/notification_template_quantum_media.xml
new file mode 100644
index 0000000..14fabce
--- /dev/null
+++ b/core/res/res/layout/notification_template_quantum_media.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:internal="http://schemas.android.com/apk/prv/res/android"
+    android:id="@+id/status_bar_latest_event_content"
+    android:layout_width="match_parent"
+    android:layout_height="64dp"
+    android:orientation="horizontal"
+    internal:layout_minHeight="64dp"
+    internal:layout_maxHeight="64dp"
+    >
+    <include layout="@layout/notification_template_icon_group"
+        android:layout_width="@dimen/notification_large_icon_width"
+        android:layout_height="@dimen/notification_large_icon_height"
+        android:layout_weight="0"
+        />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:layout_gravity="fill_vertical"
+        android:minHeight="@dimen/notification_large_icon_height"
+        android:orientation="vertical"
+        android:paddingEnd="8dp"
+        android:paddingTop="2dp"
+        android:paddingBottom="2dp"
+        android:gravity="top"
+        >
+        <LinearLayout
+            android:id="@+id/line1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="6dp"
+            android:layout_marginStart="8dp"
+            android:orientation="horizontal"
+            >
+            <TextView android:id="@+id/title"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                android:layout_weight="1"
+                />
+            <ViewStub android:id="@+id/time"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="0"
+                android:visibility="gone"
+                android:layout="@layout/notification_template_part_time"
+                />
+            <ViewStub android:id="@+id/chronometer"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="0"
+                android:visibility="gone"
+                android:layout="@layout/notification_template_part_chronometer"
+                />
+        </LinearLayout>
+        <TextView android:id="@+id/text2"
+            android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Line2"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="-2dp"
+            android:layout_marginBottom="-2dp"
+            android:layout_marginStart="8dp"
+            android:singleLine="true"
+            android:fadingEdge="horizontal"
+            android:ellipsize="marquee"
+            android:visibility="gone"
+            />
+        <ProgressBar
+            android:id="@android:id/progress"
+            android:layout_width="match_parent"
+            android:layout_height="12dp"
+            android:layout_marginStart="8dp"
+            android:visibility="gone"
+            style="@style/Widget.StatusBar.Quantum.ProgressBar"
+            />
+        <LinearLayout
+            android:id="@+id/line3"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:gravity="center_vertical"
+            android:layout_marginStart="8dp"
+            >
+            <TextView android:id="@+id/text"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_gravity="center"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:fadingEdge="horizontal"
+                />
+            <TextView android:id="@+id/info"
+                android:textAppearance="@style/TextAppearance.StatusBar.Quantum.EventContent.Info"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:layout_weight="0"
+                android:singleLine="true"
+                android:gravity="center"
+                android:paddingStart="8dp"
+                />
+        </LinearLayout>
+    </LinearLayout>
+    <LinearLayout
+        android:id="@+id/actions"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_gravity="center_vertical|end"
+        android:orientation="horizontal"
+        >
+        <!-- media buttons will be added here -->
+    </LinearLayout>
+</LinearLayout>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index ad29505..5a2609e 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -129,6 +129,10 @@
     <color name="notification_icon_bg_color">#ffa3a3a3</color>
     <color name="notification_action_legacy_color_filter">#ff555555</color>
 
+    <color name="notification_media_action_bg">#00000000</color>
+    <color name="notification_media_info_bg">#40FFFFFF</color>
+    <color name="notification_media_progress">#FFFFFFFF</color>
+
     <!-- Keyguard colors -->
     <color name="keyguard_avatar_frame_color">#ffffffff</color>
     <color name="keyguard_avatar_frame_shadow_color">#80000000</color>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index fd57c5e..4a27ebe 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -299,6 +299,10 @@
     <style name="TextAppearance.StatusBar.Quantum.EventContent.Emphasis">
         <item name="android:textColor">#66000000</item>
     </style>
+    <style name="Widget.StatusBar.Quantum.ProgressBar"
+           parent="Widget.Quantum.Light.ProgressBar.Horizontal">
+        <item name="android:progressDrawable">@drawable/notification_quantum_media_progress</item>
+    </style>
 
     <style name="Widget.StatusBar.Quantum.ProgressBar"
            parent="Widget.Quantum.Light.ProgressBar.Horizontal">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d7a5573..dcff978 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1662,13 +1662,21 @@
   <java-symbol type="layout" name="notification_template_quantum_big_picture" />
   <java-symbol type="layout" name="notification_template_quantum_big_text" />
   <java-symbol type="layout" name="notification_template_quantum_inbox" />
+  <java-symbol type="layout" name="notification_template_quantum_media" />
+  <java-symbol type="layout" name="notification_template_quantum_big_media" />
   <java-symbol type="layout" name="notification_template_icon_group" />
+  <java-symbol type="layout" name="notification_quantum_media_action" />
   <java-symbol type="color" name="notification_action_legacy_color_filter" />
   <java-symbol type="color" name="notification_icon_bg_color" />
   <java-symbol type="drawable" name="notification_icon_legacy_bg" />
   <java-symbol type="drawable" name="notification_icon_legacy_bg_inset" />
   <java-symbol type="drawable" name="notification_quantum_bg_dim" />
   <java-symbol type="drawable" name="notification_quantum_bg" />
+  <java-symbol type="drawable" name="notification_quantum_media_progress" />
+  <java-symbol type="color" name="notification_media_action_bg" />
+  <java-symbol type="color" name="notification_media_info_bg" />
+  <java-symbol type="color" name="notification_media_progress" />
+  <java-symbol type="id" name="media_action_area" />
 
     <!-- From SystemUI -->
   <java-symbol type="anim" name="push_down_in" />
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 7a86811..36cfb0f 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -764,21 +764,30 @@
         return -1;
     }
 
-    if (ctx->getBufferFormat() != buffer->format) {
-        // Return the buffer to the queue.
-        consumer->unlockBuffer(*buffer);
-        ctx->returnLockedBuffer(buffer);
+    int imgReaderFmt = ctx->getBufferFormat();
+    int bufFmt = buffer->format;
+    if (imgReaderFmt != bufFmt) {
+        // Special casing for when producer switches format
+        if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && bufFmt ==
+                HAL_PIXEL_FORMAT_YCrCb_420_SP) {
+            ctx->setBufferFormat(HAL_PIXEL_FORMAT_YCrCb_420_SP);
+            ALOGV("%s: Overriding NV21 to YUV_420_888.", __FUNCTION__);
+        } else {
+            // Return the buffer to the queue.
+            consumer->unlockBuffer(*buffer);
+            ctx->returnLockedBuffer(buffer);
 
-        // Throw exception
-        ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
-              buffer->format, ctx->getBufferFormat());
-        String8 msg;
-        msg.appendFormat("The producer output buffer format 0x%x doesn't "
-                "match the ImageReader's configured buffer format 0x%x.",
-                buffer->format, ctx->getBufferFormat());
-        jniThrowException(env, "java/lang/UnsupportedOperationException",
-                msg.string());
-        return -1;
+            // Throw exception
+            ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
+                    buffer->format, ctx->getBufferFormat());
+            String8 msg;
+            msg.appendFormat("The producer output buffer format 0x%x doesn't "
+                    "match the ImageReader's configured buffer format 0x%x.",
+                    buffer->format, ctx->getBufferFormat());
+            jniThrowException(env, "java/lang/UnsupportedOperationException",
+                    msg.string());
+            return -1;
+        }
     }
     // Set SurfaceImage instance member variables
     Image_setBuffer(env, image, buffer);
diff --git a/opengl/java/android/opengl/GLES31.java b/opengl/java/android/opengl/GLES31.java
new file mode 100644
index 0000000..3cbaa60
--- /dev/null
+++ b/opengl/java/android/opengl/GLES31.java
@@ -0,0 +1,1099 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This source file is automatically generated
+
+package android.opengl;
+
+/** OpenGL ES 3.1
+ */
+public class GLES31 extends GLES30 {
+
+    public static final int GL_VERTEX_SHADER_BIT                            = 0x00000001;
+    public static final int GL_FRAGMENT_SHADER_BIT                          = 0x00000002;
+    public static final int GL_UNIFORM_BARRIER_BIT                          = 0x00000004;
+    public static final int GL_TEXTURE_FETCH_BARRIER_BIT                    = 0x00000008;
+    public static final int GL_COMPUTE_SHADER_BIT                           = 0x00000020;
+    public static final int GL_COMMAND_BARRIER_BIT                          = 0x00000040;
+    public static final int GL_PIXEL_BUFFER_BARRIER_BIT                     = 0x00000080;
+    public static final int GL_TEXTURE_UPDATE_BARRIER_BIT                   = 0x00000100;
+    public static final int GL_BUFFER_UPDATE_BARRIER_BIT                    = 0x00000200;
+    public static final int GL_FRAMEBUFFER_BARRIER_BIT                      = 0x00000400;
+    public static final int GL_TRANSFORM_FEEDBACK_BARRIER_BIT               = 0x00000800;
+    public static final int GL_ATOMIC_COUNTER_BARRIER_BIT                   = 0x00001000;
+    public static final int GL_SHADER_STORAGE_BARRIER_BIT                   = 0x00002000;
+    public static final int GL_ALL_SHADER_BITS                              = -1; // 0xFFFFFFFF
+
+    public static final int GL_TEXTURE_WIDTH                                = 0x1000;
+    public static final int GL_TEXTURE_HEIGHT                               = 0x1001;
+    public static final int GL_TEXTURE_INTERNAL_FORMAT                      = 0x1003;
+    public static final int GL_STENCIL_INDEX                                = 0x1901;
+    public static final int GL_TEXTURE_RED_SIZE                             = 0x805C;
+    public static final int GL_TEXTURE_GREEN_SIZE                           = 0x805D;
+    public static final int GL_TEXTURE_BLUE_SIZE                            = 0x805E;
+    public static final int GL_TEXTURE_ALPHA_SIZE                           = 0x805F;
+    public static final int GL_TEXTURE_DEPTH                                = 0x8071;
+    public static final int GL_PROGRAM_SEPARABLE                            = 0x8258;
+    public static final int GL_ACTIVE_PROGRAM                               = 0x8259;
+    public static final int GL_PROGRAM_PIPELINE_BINDING                     = 0x825A;
+    public static final int GL_MAX_COMPUTE_SHARED_MEMORY_SIZE               = 0x8262;
+    public static final int GL_MAX_COMPUTE_UNIFORM_COMPONENTS               = 0x8263;
+    public static final int GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS           = 0x8264;
+    public static final int GL_MAX_COMPUTE_ATOMIC_COUNTERS                  = 0x8265;
+    public static final int GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS      = 0x8266;
+    public static final int GL_COMPUTE_WORK_GROUP_SIZE                      = 0x8267;
+    public static final int GL_MAX_UNIFORM_LOCATIONS                        = 0x826E;
+    public static final int GL_VERTEX_ATTRIB_BINDING                        = 0x82D4;
+    public static final int GL_VERTEX_ATTRIB_RELATIVE_OFFSET                = 0x82D5;
+    public static final int GL_VERTEX_BINDING_DIVISOR                       = 0x82D6;
+    public static final int GL_VERTEX_BINDING_OFFSET                        = 0x82D7;
+    public static final int GL_VERTEX_BINDING_STRIDE                        = 0x82D8;
+    public static final int GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET            = 0x82D9;
+    public static final int GL_MAX_VERTEX_ATTRIB_BINDINGS                   = 0x82DA;
+    public static final int GL_MAX_VERTEX_ATTRIB_STRIDE                     = 0x82E5;
+    public static final int GL_TEXTURE_COMPRESSED                           = 0x86A1;
+    public static final int GL_TEXTURE_DEPTH_SIZE                           = 0x884A;
+    public static final int GL_READ_ONLY                                    = 0x88B8;
+    public static final int GL_WRITE_ONLY                                   = 0x88B9;
+    public static final int GL_READ_WRITE                                   = 0x88BA;
+    public static final int GL_TEXTURE_STENCIL_SIZE                         = 0x88F1;
+    public static final int GL_TEXTURE_RED_TYPE                             = 0x8C10;
+    public static final int GL_TEXTURE_GREEN_TYPE                           = 0x8C11;
+    public static final int GL_TEXTURE_BLUE_TYPE                            = 0x8C12;
+    public static final int GL_TEXTURE_ALPHA_TYPE                           = 0x8C13;
+    public static final int GL_TEXTURE_DEPTH_TYPE                           = 0x8C16;
+    public static final int GL_TEXTURE_SHARED_SIZE                          = 0x8C3F;
+    public static final int GL_SAMPLE_POSITION                              = 0x8E50;
+    public static final int GL_SAMPLE_MASK                                  = 0x8E51;
+    public static final int GL_SAMPLE_MASK_VALUE                            = 0x8E52;
+    public static final int GL_MAX_SAMPLE_MASK_WORDS                        = 0x8E59;
+    public static final int GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET            = 0x8E5E;
+    public static final int GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET            = 0x8E5F;
+    public static final int GL_MAX_IMAGE_UNITS                              = 0x8F38;
+    public static final int GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES         = 0x8F39;
+    public static final int GL_IMAGE_BINDING_NAME                           = 0x8F3A;
+    public static final int GL_IMAGE_BINDING_LEVEL                          = 0x8F3B;
+    public static final int GL_IMAGE_BINDING_LAYERED                        = 0x8F3C;
+    public static final int GL_IMAGE_BINDING_LAYER                          = 0x8F3D;
+    public static final int GL_IMAGE_BINDING_ACCESS                         = 0x8F3E;
+    public static final int GL_DRAW_INDIRECT_BUFFER                         = 0x8F3F;
+    public static final int GL_DRAW_INDIRECT_BUFFER_BINDING                 = 0x8F43;
+    public static final int GL_VERTEX_BINDING_BUFFER                        = 0x8F4F;
+    public static final int GL_IMAGE_2D                                     = 0x904D;
+    public static final int GL_IMAGE_3D                                     = 0x904E;
+    public static final int GL_IMAGE_CUBE                                   = 0x9050;
+    public static final int GL_IMAGE_2D_ARRAY                               = 0x9053;
+    public static final int GL_INT_IMAGE_2D                                 = 0x9058;
+    public static final int GL_INT_IMAGE_3D                                 = 0x9059;
+    public static final int GL_INT_IMAGE_CUBE                               = 0x905B;
+    public static final int GL_INT_IMAGE_2D_ARRAY                           = 0x905E;
+    public static final int GL_UNSIGNED_INT_IMAGE_2D                        = 0x9063;
+    public static final int GL_UNSIGNED_INT_IMAGE_3D                        = 0x9064;
+    public static final int GL_UNSIGNED_INT_IMAGE_CUBE                      = 0x9066;
+    public static final int GL_UNSIGNED_INT_IMAGE_2D_ARRAY                  = 0x9069;
+    public static final int GL_IMAGE_BINDING_FORMAT                         = 0x906E;
+    public static final int GL_IMAGE_FORMAT_COMPATIBILITY_TYPE              = 0x90C7;
+    public static final int GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE           = 0x90C8;
+    public static final int GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS          = 0x90C9;
+    public static final int GL_MAX_VERTEX_IMAGE_UNIFORMS                    = 0x90CA;
+    public static final int GL_MAX_FRAGMENT_IMAGE_UNIFORMS                  = 0x90CE;
+    public static final int GL_MAX_COMBINED_IMAGE_UNIFORMS                  = 0x90CF;
+    public static final int GL_SHADER_STORAGE_BUFFER                        = 0x90D2;
+    public static final int GL_SHADER_STORAGE_BUFFER_BINDING                = 0x90D3;
+    public static final int GL_SHADER_STORAGE_BUFFER_START                  = 0x90D4;
+    public static final int GL_SHADER_STORAGE_BUFFER_SIZE                   = 0x90D5;
+    public static final int GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS             = 0x90D6;
+    public static final int GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS           = 0x90DA;
+    public static final int GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS            = 0x90DB;
+    public static final int GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS           = 0x90DC;
+    public static final int GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS           = 0x90DD;
+    public static final int GL_MAX_SHADER_STORAGE_BLOCK_SIZE                = 0x90DE;
+    public static final int GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT       = 0x90DF;
+    public static final int GL_DEPTH_STENCIL_TEXTURE_MODE                   = 0x90EA;
+    public static final int GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS           = 0x90EB;
+    public static final int GL_DISPATCH_INDIRECT_BUFFER                     = 0x90EE;
+    public static final int GL_DISPATCH_INDIRECT_BUFFER_BINDING             = 0x90EF;
+    public static final int GL_TEXTURE_2D_MULTISAMPLE                       = 0x9100;
+    public static final int GL_TEXTURE_BINDING_2D_MULTISAMPLE               = 0x9104;
+    public static final int GL_TEXTURE_SAMPLES                              = 0x9106;
+    public static final int GL_TEXTURE_FIXED_SAMPLE_LOCATIONS               = 0x9107;
+    public static final int GL_SAMPLER_2D_MULTISAMPLE                       = 0x9108;
+    public static final int GL_INT_SAMPLER_2D_MULTISAMPLE                   = 0x9109;
+    public static final int GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE          = 0x910A;
+    public static final int GL_MAX_COLOR_TEXTURE_SAMPLES                    = 0x910E;
+    public static final int GL_MAX_DEPTH_TEXTURE_SAMPLES                    = 0x910F;
+    public static final int GL_MAX_INTEGER_SAMPLES                          = 0x9110;
+    public static final int GL_COMPUTE_SHADER                               = 0x91B9;
+    public static final int GL_MAX_COMPUTE_UNIFORM_BLOCKS                   = 0x91BB;
+    public static final int GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS              = 0x91BC;
+    public static final int GL_MAX_COMPUTE_IMAGE_UNIFORMS                   = 0x91BD;
+    public static final int GL_MAX_COMPUTE_WORK_GROUP_COUNT                 = 0x91BE;
+    public static final int GL_MAX_COMPUTE_WORK_GROUP_SIZE                  = 0x91BF;
+    public static final int GL_ATOMIC_COUNTER_BUFFER                        = 0x92C0;
+    public static final int GL_ATOMIC_COUNTER_BUFFER_BINDING                = 0x92C1;
+    public static final int GL_ATOMIC_COUNTER_BUFFER_START                  = 0x92C2;
+    public static final int GL_ATOMIC_COUNTER_BUFFER_SIZE                   = 0x92C3;
+    public static final int GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS            = 0x92CC;
+    public static final int GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS          = 0x92D0;
+    public static final int GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS          = 0x92D1;
+    public static final int GL_MAX_VERTEX_ATOMIC_COUNTERS                   = 0x92D2;
+    public static final int GL_MAX_FRAGMENT_ATOMIC_COUNTERS                 = 0x92D6;
+    public static final int GL_MAX_COMBINED_ATOMIC_COUNTERS                 = 0x92D7;
+    public static final int GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE               = 0x92D8;
+    public static final int GL_ACTIVE_ATOMIC_COUNTER_BUFFERS                = 0x92D9;
+    public static final int GL_UNSIGNED_INT_ATOMIC_COUNTER                  = 0x92DB;
+    public static final int GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS           = 0x92DC;
+    public static final int GL_UNIFORM                                      = 0x92E1;
+    public static final int GL_UNIFORM_BLOCK                                = 0x92E2;
+    public static final int GL_PROGRAM_INPUT                                = 0x92E3;
+    public static final int GL_PROGRAM_OUTPUT                               = 0x92E4;
+    public static final int GL_BUFFER_VARIABLE                              = 0x92E5;
+    public static final int GL_SHADER_STORAGE_BLOCK                         = 0x92E6;
+    public static final int GL_TRANSFORM_FEEDBACK_VARYING                   = 0x92F4;
+    public static final int GL_ACTIVE_RESOURCES                             = 0x92F5;
+    public static final int GL_MAX_NAME_LENGTH                              = 0x92F6;
+    public static final int GL_MAX_NUM_ACTIVE_VARIABLES                     = 0x92F7;
+    public static final int GL_NAME_LENGTH                                  = 0x92F9;
+    public static final int GL_TYPE                                         = 0x92FA;
+    public static final int GL_ARRAY_SIZE                                   = 0x92FB;
+    public static final int GL_OFFSET                                       = 0x92FC;
+    public static final int GL_BLOCK_INDEX                                  = 0x92FD;
+    public static final int GL_ARRAY_STRIDE                                 = 0x92FE;
+    public static final int GL_MATRIX_STRIDE                                = 0x92FF;
+    public static final int GL_IS_ROW_MAJOR                                 = 0x9300;
+    public static final int GL_ATOMIC_COUNTER_BUFFER_INDEX                  = 0x9301;
+    public static final int GL_BUFFER_BINDING                               = 0x9302;
+    public static final int GL_BUFFER_DATA_SIZE                             = 0x9303;
+    public static final int GL_NUM_ACTIVE_VARIABLES                         = 0x9304;
+    public static final int GL_ACTIVE_VARIABLES                             = 0x9305;
+    public static final int GL_REFERENCED_BY_VERTEX_SHADER                  = 0x9306;
+    public static final int GL_REFERENCED_BY_FRAGMENT_SHADER                = 0x930A;
+    public static final int GL_REFERENCED_BY_COMPUTE_SHADER                 = 0x930B;
+    public static final int GL_TOP_LEVEL_ARRAY_SIZE                         = 0x930C;
+    public static final int GL_TOP_LEVEL_ARRAY_STRIDE                       = 0x930D;
+    public static final int GL_LOCATION                                     = 0x930E;
+    public static final int GL_FRAMEBUFFER_DEFAULT_WIDTH                    = 0x9310;
+    public static final int GL_FRAMEBUFFER_DEFAULT_HEIGHT                   = 0x9311;
+    public static final int GL_FRAMEBUFFER_DEFAULT_SAMPLES                  = 0x9313;
+    public static final int GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS   = 0x9314;
+    public static final int GL_MAX_FRAMEBUFFER_WIDTH                        = 0x9315;
+    public static final int GL_MAX_FRAMEBUFFER_HEIGHT                       = 0x9316;
+    public static final int GL_MAX_FRAMEBUFFER_SAMPLES                      = 0x9318;
+
+    native private static void _nativeClassInit();
+    static {
+        _nativeClassInit();
+    }
+
+    private GLES31() {}
+    // C function void glDispatchCompute ( GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z )
+
+    public static native void glDispatchCompute(
+        int num_groups_x,
+        int num_groups_y,
+        int num_groups_z
+    );
+
+    // C function void glDispatchComputeIndirect ( GLintptr indirect );
+
+    public static native void glDispatchComputeIndirect(long indirect);
+
+    // C function void glDrawArraysIndirect ( GLenum mode, const void *indirect );
+
+    public static native void glDrawArraysIndirect(int mode, long indirect);
+
+    // C function glDrawElementsIndirect ( GLenum mode, GLenum type, const void *indirect );
+
+    public static native void glDrawElementsIndirect(int mode, int type, long indirect);
+
+    // C function void glFramebufferParameteri ( GLenum target, GLenum pname, GLint param )
+
+    public static native void glFramebufferParameteri(
+        int target,
+        int pname,
+        int param
+    );
+
+    // C function void glGetFramebufferParameteriv ( GLenum target, GLenum pname, GLint *params )
+
+    public static native void glGetFramebufferParameteriv(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetFramebufferParameteriv ( GLenum target, GLenum pname, GLint *params )
+
+    public static native void glGetFramebufferParameteriv(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetProgramInterfaceiv ( GLuint program, GLenum programInterface, GLenum pname, GLint *params )
+
+    public static native void glGetProgramInterfaceiv(
+        int program,
+        int programInterface,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetProgramInterfaceiv ( GLuint program, GLenum programInterface, GLenum pname, GLint *params )
+
+    public static native void glGetProgramInterfaceiv(
+        int program,
+        int programInterface,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function GLuint glGetProgramResourceIndex ( GLuint program, GLenum programInterface, const GLchar *name )
+
+    public static native int glGetProgramResourceIndex(
+        int program,
+        int programInterface,
+        String name
+    );
+
+    // C function void glGetProgramResourceName ( GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name )
+
+    public static native String glGetProgramResourceName(
+        int program,
+        int programInterface,
+        int index
+    );
+
+    // C function void glGetProgramResourceiv ( GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params )
+
+    public static native void glGetProgramResourceiv(
+        int program,
+        int programInterface,
+        int index,
+        int propCount,
+        int[] props,
+        int propsOffset,
+        int bufSize,
+        int[] length,
+        int lengthOffset,
+        int[] params,
+        int paramsOffset
+    );
+
+    // C function void glGetProgramResourceiv ( GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params )
+
+    public static native void glGetProgramResourceiv(
+        int program,
+        int programInterface,
+        int index,
+        int propCount,
+        java.nio.IntBuffer props,
+        int bufSize,
+        java.nio.IntBuffer length,
+        java.nio.IntBuffer params
+    );
+
+    // C function GLint glGetProgramResourceLocation ( GLuint program, GLenum programInterface, const GLchar *name )
+
+    public static native int glGetProgramResourceLocation(
+        int program,
+        int programInterface,
+        String name
+    );
+
+    // C function void glUseProgramStages ( GLuint pipeline, GLbitfield stages, GLuint program )
+
+    public static native void glUseProgramStages(
+        int pipeline,
+        int stages,
+        int program
+    );
+
+    // C function void glActiveShaderProgram ( GLuint pipeline, GLuint program )
+
+    public static native void glActiveShaderProgram(
+        int pipeline,
+        int program
+    );
+
+    // C function GLuint glCreateShaderProgramv ( GLenum type, GLsizei count, const GLchar *const *strings )
+
+    public static native int glCreateShaderProgramv(
+        int type,
+        String[] strings
+    );
+
+    // C function void glBindProgramPipeline ( GLuint pipeline )
+
+    public static native void glBindProgramPipeline(
+        int pipeline
+    );
+
+    // C function void glDeleteProgramPipelines ( GLsizei n, const GLuint *pipelines )
+
+    public static native void glDeleteProgramPipelines(
+        int n,
+        int[] pipelines,
+        int offset
+    );
+
+    // C function void glDeleteProgramPipelines ( GLsizei n, const GLuint *pipelines )
+
+    public static native void glDeleteProgramPipelines(
+        int n,
+        java.nio.IntBuffer pipelines
+    );
+
+    // C function void glGenProgramPipelines ( GLsizei n, GLuint *pipelines )
+
+    public static native void glGenProgramPipelines(
+        int n,
+        int[] pipelines,
+        int offset
+    );
+
+    // C function void glGenProgramPipelines ( GLsizei n, GLuint *pipelines )
+
+    public static native void glGenProgramPipelines(
+        int n,
+        java.nio.IntBuffer pipelines
+    );
+
+    // C function GLboolean glIsProgramPipeline ( GLuint pipeline )
+
+    public static native boolean glIsProgramPipeline(
+        int pipeline
+    );
+
+    // C function void glGetProgramPipelineiv ( GLuint pipeline, GLenum pname, GLint *params )
+
+    public static native void glGetProgramPipelineiv(
+        int pipeline,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetProgramPipelineiv ( GLuint pipeline, GLenum pname, GLint *params )
+
+    public static native void glGetProgramPipelineiv(
+        int pipeline,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glProgramUniform1i ( GLuint program, GLint location, GLint v0 )
+
+    public static native void glProgramUniform1i(
+        int program,
+        int location,
+        int v0
+    );
+
+    // C function void glProgramUniform2i ( GLuint program, GLint location, GLint v0, GLint v1 )
+
+    public static native void glProgramUniform2i(
+        int program,
+        int location,
+        int v0,
+        int v1
+    );
+
+    // C function void glProgramUniform3i ( GLuint program, GLint location, GLint v0, GLint v1, GLint v2 )
+
+    public static native void glProgramUniform3i(
+        int program,
+        int location,
+        int v0,
+        int v1,
+        int v2
+    );
+
+    // C function void glProgramUniform4i ( GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3 )
+
+    public static native void glProgramUniform4i(
+        int program,
+        int location,
+        int v0,
+        int v1,
+        int v2,
+        int v3
+    );
+
+    // C function void glProgramUniform1ui ( GLuint program, GLint location, GLuint v0 )
+
+    public static native void glProgramUniform1ui(
+        int program,
+        int location,
+        int v0
+    );
+
+    // C function void glProgramUniform2ui ( GLuint program, GLint location, GLuint v0, GLuint v1 )
+
+    public static native void glProgramUniform2ui(
+        int program,
+        int location,
+        int v0,
+        int v1
+    );
+
+    // C function void glProgramUniform3ui ( GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2 )
+
+    public static native void glProgramUniform3ui(
+        int program,
+        int location,
+        int v0,
+        int v1,
+        int v2
+    );
+
+    // C function void glProgramUniform4ui ( GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3 )
+
+    public static native void glProgramUniform4ui(
+        int program,
+        int location,
+        int v0,
+        int v1,
+        int v2,
+        int v3
+    );
+
+    // C function void glProgramUniform1f ( GLuint program, GLint location, GLfloat v0 )
+
+    public static native void glProgramUniform1f(
+        int program,
+        int location,
+        float v0
+    );
+
+    // C function void glProgramUniform2f ( GLuint program, GLint location, GLfloat v0, GLfloat v1 )
+
+    public static native void glProgramUniform2f(
+        int program,
+        int location,
+        float v0,
+        float v1
+    );
+
+    // C function void glProgramUniform3f ( GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2 )
+
+    public static native void glProgramUniform3f(
+        int program,
+        int location,
+        float v0,
+        float v1,
+        float v2
+    );
+
+    // C function void glProgramUniform4f ( GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3 )
+
+    public static native void glProgramUniform4f(
+        int program,
+        int location,
+        float v0,
+        float v1,
+        float v2,
+        float v3
+    );
+
+    // C function void glProgramUniform1iv ( GLuint program, GLint location, GLsizei count, const GLint *value )
+
+    public static native void glProgramUniform1iv(
+        int program,
+        int location,
+        int count,
+        int[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform1iv ( GLuint program, GLint location, GLsizei count, const GLint *value )
+
+    public static native void glProgramUniform1iv(
+        int program,
+        int location,
+        int count,
+        java.nio.IntBuffer value
+    );
+
+    // C function void glProgramUniform2iv ( GLuint program, GLint location, GLsizei count, const GLint *value )
+
+    public static native void glProgramUniform2iv(
+        int program,
+        int location,
+        int count,
+        int[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform2iv ( GLuint program, GLint location, GLsizei count, const GLint *value )
+
+    public static native void glProgramUniform2iv(
+        int program,
+        int location,
+        int count,
+        java.nio.IntBuffer value
+    );
+
+    // C function void glProgramUniform3iv ( GLuint program, GLint location, GLsizei count, const GLint *value )
+
+    public static native void glProgramUniform3iv(
+        int program,
+        int location,
+        int count,
+        int[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform3iv ( GLuint program, GLint location, GLsizei count, const GLint *value )
+
+    public static native void glProgramUniform3iv(
+        int program,
+        int location,
+        int count,
+        java.nio.IntBuffer value
+    );
+
+    // C function void glProgramUniform4iv ( GLuint program, GLint location, GLsizei count, const GLint *value )
+
+    public static native void glProgramUniform4iv(
+        int program,
+        int location,
+        int count,
+        int[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform4iv ( GLuint program, GLint location, GLsizei count, const GLint *value )
+
+    public static native void glProgramUniform4iv(
+        int program,
+        int location,
+        int count,
+        java.nio.IntBuffer value
+    );
+
+    // C function void glProgramUniform1uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value )
+
+    public static native void glProgramUniform1uiv(
+        int program,
+        int location,
+        int count,
+        int[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform1uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value )
+
+    public static native void glProgramUniform1uiv(
+        int program,
+        int location,
+        int count,
+        java.nio.IntBuffer value
+    );
+
+    // C function void glProgramUniform2uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value )
+
+    public static native void glProgramUniform2uiv(
+        int program,
+        int location,
+        int count,
+        int[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform2uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value )
+
+    public static native void glProgramUniform2uiv(
+        int program,
+        int location,
+        int count,
+        java.nio.IntBuffer value
+    );
+
+    // C function void glProgramUniform3uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value )
+
+    public static native void glProgramUniform3uiv(
+        int program,
+        int location,
+        int count,
+        int[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform3uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value )
+
+    public static native void glProgramUniform3uiv(
+        int program,
+        int location,
+        int count,
+        java.nio.IntBuffer value
+    );
+
+    // C function void glProgramUniform4uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value )
+
+    public static native void glProgramUniform4uiv(
+        int program,
+        int location,
+        int count,
+        int[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform4uiv ( GLuint program, GLint location, GLsizei count, const GLuint *value )
+
+    public static native void glProgramUniform4uiv(
+        int program,
+        int location,
+        int count,
+        java.nio.IntBuffer value
+    );
+
+    // C function void glProgramUniform1fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value )
+
+    public static native void glProgramUniform1fv(
+        int program,
+        int location,
+        int count,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform1fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value )
+
+    public static native void glProgramUniform1fv(
+        int program,
+        int location,
+        int count,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniform2fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value )
+
+    public static native void glProgramUniform2fv(
+        int program,
+        int location,
+        int count,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform2fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value )
+
+    public static native void glProgramUniform2fv(
+        int program,
+        int location,
+        int count,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniform3fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value )
+
+    public static native void glProgramUniform3fv(
+        int program,
+        int location,
+        int count,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform3fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value )
+
+    public static native void glProgramUniform3fv(
+        int program,
+        int location,
+        int count,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniform4fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value )
+
+    public static native void glProgramUniform4fv(
+        int program,
+        int location,
+        int count,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniform4fv ( GLuint program, GLint location, GLsizei count, const GLfloat *value )
+
+    public static native void glProgramUniform4fv(
+        int program,
+        int location,
+        int count,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniformMatrix2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix2fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniformMatrix2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix2fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniformMatrix3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix3fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniformMatrix3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix3fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniformMatrix4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix4fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniformMatrix4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix4fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniformMatrix2x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix2x3fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniformMatrix2x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix2x3fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniformMatrix3x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix3x2fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniformMatrix3x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix3x2fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniformMatrix2x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix2x4fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniformMatrix2x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix2x4fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniformMatrix4x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix4x2fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniformMatrix4x2fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix4x2fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniformMatrix3x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix3x4fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniformMatrix3x4fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix3x4fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glProgramUniformMatrix4x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix4x3fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        float[] value,
+        int offset
+    );
+
+    // C function void glProgramUniformMatrix4x3fv ( GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value )
+
+    public static native void glProgramUniformMatrix4x3fv(
+        int program,
+        int location,
+        int count,
+        boolean transpose,
+        java.nio.FloatBuffer value
+    );
+
+    // C function void glValidateProgramPipeline ( GLuint pipeline )
+
+    public static native void glValidateProgramPipeline(
+        int pipeline
+    );
+
+    // C function void glGetProgramPipelineInfoLog( GLuint program, GLsizei maxLength, GLsizei * length, GLchar * infoLog);
+
+    public static native String glGetProgramPipelineInfoLog(
+        int program
+    );
+
+    // C function void glBindImageTexture ( GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format )
+
+    public static native void glBindImageTexture(
+        int unit,
+        int texture,
+        int level,
+        boolean layered,
+        int layer,
+        int access,
+        int format
+    );
+
+    // C function void glGetBooleani_v ( GLenum target, GLuint index, GLboolean *data )
+
+    public static native void glGetBooleani_v(
+        int target,
+        int index,
+        boolean[] data,
+        int offset
+    );
+
+    // C function void glGetBooleani_v ( GLenum target, GLuint index, GLboolean *data )
+
+    public static native void glGetBooleani_v(
+        int target,
+        int index,
+        java.nio.IntBuffer data
+    );
+
+    // C function void glMemoryBarrier ( GLbitfield barriers )
+
+    public static native void glMemoryBarrier(
+        int barriers
+    );
+
+    // C function void glMemoryBarrierByRegion ( GLbitfield barriers )
+
+    public static native void glMemoryBarrierByRegion(
+        int barriers
+    );
+
+    // C function void glTexStorage2DMultisample ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations )
+
+    public static native void glTexStorage2DMultisample(
+        int target,
+        int samples,
+        int internalformat,
+        int width,
+        int height,
+        boolean fixedsamplelocations
+    );
+
+    // C function void glGetMultisamplefv ( GLenum pname, GLuint index, GLfloat *val )
+
+    public static native void glGetMultisamplefv(
+        int pname,
+        int index,
+        float[] val,
+        int offset
+    );
+
+    // C function void glGetMultisamplefv ( GLenum pname, GLuint index, GLfloat *val )
+
+    public static native void glGetMultisamplefv(
+        int pname,
+        int index,
+        java.nio.FloatBuffer val
+    );
+
+    // C function void glSampleMaski ( GLuint maskNumber, GLbitfield mask )
+
+    public static native void glSampleMaski(
+        int maskNumber,
+        int mask
+    );
+
+    // C function void glGetTexLevelParameteriv ( GLenum target, GLint level, GLenum pname, GLint *params )
+
+    public static native void glGetTexLevelParameteriv(
+        int target,
+        int level,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetTexLevelParameteriv ( GLenum target, GLint level, GLenum pname, GLint *params )
+
+    public static native void glGetTexLevelParameteriv(
+        int target,
+        int level,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetTexLevelParameterfv ( GLenum target, GLint level, GLenum pname, GLfloat *params )
+
+    public static native void glGetTexLevelParameterfv(
+        int target,
+        int level,
+        int pname,
+        float[] params,
+        int offset
+    );
+
+    // C function void glGetTexLevelParameterfv ( GLenum target, GLint level, GLenum pname, GLfloat *params )
+
+    public static native void glGetTexLevelParameterfv(
+        int target,
+        int level,
+        int pname,
+        java.nio.FloatBuffer params
+    );
+
+    // C function void glBindVertexBuffer ( GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride )
+
+    public static native void glBindVertexBuffer(
+        int bindingindex,
+        int buffer,
+        long offset,
+        int stride
+    );
+
+    // C function void glVertexAttribFormat ( GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset )
+
+    public static native void glVertexAttribFormat(
+        int attribindex,
+        int size,
+        int type,
+        boolean normalized,
+        int relativeoffset
+    );
+
+    // C function void glVertexAttribIFormat ( GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset )
+
+    public static native void glVertexAttribIFormat(
+        int attribindex,
+        int size,
+        int type,
+        int relativeoffset
+    );
+
+    // C function void glVertexAttribBinding ( GLuint attribindex, GLuint bindingindex )
+
+    public static native void glVertexAttribBinding(
+        int attribindex,
+        int bindingindex
+    );
+
+    // C function void glVertexBindingDivisor ( GLuint bindingindex, GLuint divisor )
+
+    public static native void glVertexBindingDivisor(
+        int bindingindex,
+        int divisor
+    );
+
+}
diff --git a/opengl/java/android/opengl/GLES31Ext.java b/opengl/java/android/opengl/GLES31Ext.java
new file mode 100644
index 0000000..c362a36
--- /dev/null
+++ b/opengl/java/android/opengl/GLES31Ext.java
@@ -0,0 +1,678 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// This source file is automatically generated
+
+package android.opengl;
+
+public class GLES31Ext {
+
+    // GL_KHR_blend_equation_advanced
+    public static final int GL_BLEND_ADVANCED_COHERENT_KHR                          = 0x9285;
+    public static final int GL_MULTIPLY_KHR                                         = 0x9294;
+    public static final int GL_SCREEN_KHR                                           = 0x9295;
+    public static final int GL_OVERLAY_KHR                                          = 0x9296;
+    public static final int GL_DARKEN_KHR                                           = 0x9297;
+    public static final int GL_LIGHTEN_KHR                                          = 0x9298;
+    public static final int GL_COLORDODGE_KHR                                       = 0x9299;
+    public static final int GL_COLORBURN_KHR                                        = 0x929A;
+    public static final int GL_HARDLIGHT_KHR                                        = 0x929B;
+    public static final int GL_SOFTLIGHT_KHR                                        = 0x929C;
+    public static final int GL_DIFFERENCE_KHR                                       = 0x929E;
+    public static final int GL_EXCLUSION_KHR                                        = 0x92A0;
+    public static final int GL_HSL_HUE_KHR                                          = 0x92AD;
+    public static final int GL_HSL_SATURATION_KHR                                   = 0x92AE;
+    public static final int GL_HSL_COLOR_KHR                                        = 0x92AF;
+    public static final int GL_HSL_LUMINOSITY_KHR                                   = 0x92B0;
+
+    // GL_KHR_debug
+    public static final int GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR                         = 0x8242;
+    public static final int GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR                 = 0x8243;
+    public static final int GL_DEBUG_CALLBACK_FUNCTION_KHR                          = 0x8244;
+    public static final int GL_DEBUG_CALLBACK_USER_PARAM_KHR                        = 0x8245;
+    public static final int GL_DEBUG_SOURCE_API_KHR                                 = 0x8246;
+    public static final int GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR                       = 0x8247;
+    public static final int GL_DEBUG_SOURCE_SHADER_COMPILER_KHR                     = 0x8248;
+    public static final int GL_DEBUG_SOURCE_THIRD_PARTY_KHR                         = 0x8249;
+    public static final int GL_DEBUG_SOURCE_APPLICATION_KHR                         = 0x824A;
+    public static final int GL_DEBUG_SOURCE_OTHER_KHR                               = 0x824B;
+    public static final int GL_DEBUG_TYPE_ERROR_KHR                                 = 0x824C;
+    public static final int GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR                   = 0x824D;
+    public static final int GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR                    = 0x824E;
+    public static final int GL_DEBUG_TYPE_PORTABILITY_KHR                           = 0x824F;
+    public static final int GL_DEBUG_TYPE_PERFORMANCE_KHR                           = 0x8250;
+    public static final int GL_DEBUG_TYPE_OTHER_KHR                                 = 0x8251;
+    public static final int GL_DEBUG_TYPE_MARKER_KHR                                = 0x8268;
+    public static final int GL_DEBUG_TYPE_PUSH_GROUP_KHR                            = 0x8269;
+    public static final int GL_DEBUG_TYPE_POP_GROUP_KHR                             = 0x826A;
+    public static final int GL_DEBUG_SEVERITY_NOTIFICATION_KHR                      = 0x826B;
+    public static final int GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR                      = 0x826C;
+    public static final int GL_DEBUG_GROUP_STACK_DEPTH_KHR                          = 0x826D;
+    public static final int GL_BUFFER_KHR                                           = 0x82E0;
+    public static final int GL_SHADER_KHR                                           = 0x82E1;
+    public static final int GL_PROGRAM_KHR                                          = 0x82E2;
+    public static final int GL_VERTEX_ARRAY_KHR                                     = 0x8074;
+    public static final int GL_QUERY_KHR                                            = 0x82E3;
+    public static final int GL_SAMPLER_KHR                                          = 0x82E6;
+    public static final int GL_MAX_LABEL_LENGTH_KHR                                 = 0x82E8;
+    public static final int GL_MAX_DEBUG_MESSAGE_LENGTH_KHR                         = 0x9143;
+    public static final int GL_MAX_DEBUG_LOGGED_MESSAGES_KHR                        = 0x9144;
+    public static final int GL_DEBUG_LOGGED_MESSAGES_KHR                            = 0x9145;
+    public static final int GL_DEBUG_SEVERITY_HIGH_KHR                              = 0x9146;
+    public static final int GL_DEBUG_SEVERITY_MEDIUM_KHR                            = 0x9147;
+    public static final int GL_DEBUG_SEVERITY_LOW_KHR                               = 0x9148;
+    public static final int GL_DEBUG_OUTPUT_KHR                                     = 0x92E0;
+    public static final int GL_CONTEXT_FLAG_DEBUG_BIT_KHR                           = 0x00000002;
+    public static final int GL_STACK_OVERFLOW_KHR                                   = 0x0503;
+    public static final int GL_STACK_UNDERFLOW_KHR                                  = 0x0504;
+
+    // GL_KHR_texture_compression_astc_ldr
+    public static final int GL_COMPRESSED_RGBA_ASTC_4x4_KHR                         = 0x93B0;
+    public static final int GL_COMPRESSED_RGBA_ASTC_5x4_KHR                         = 0x93B1;
+    public static final int GL_COMPRESSED_RGBA_ASTC_5x5_KHR                         = 0x93B2;
+    public static final int GL_COMPRESSED_RGBA_ASTC_6x5_KHR                         = 0x93B3;
+    public static final int GL_COMPRESSED_RGBA_ASTC_6x6_KHR                         = 0x93B4;
+    public static final int GL_COMPRESSED_RGBA_ASTC_8x5_KHR                         = 0x93B5;
+    public static final int GL_COMPRESSED_RGBA_ASTC_8x6_KHR                         = 0x93B6;
+    public static final int GL_COMPRESSED_RGBA_ASTC_8x8_KHR                         = 0x93B7;
+    public static final int GL_COMPRESSED_RGBA_ASTC_10x5_KHR                        = 0x93B8;
+    public static final int GL_COMPRESSED_RGBA_ASTC_10x6_KHR                        = 0x93B9;
+    public static final int GL_COMPRESSED_RGBA_ASTC_10x8_KHR                        = 0x93BA;
+    public static final int GL_COMPRESSED_RGBA_ASTC_10x10_KHR                       = 0x93BB;
+    public static final int GL_COMPRESSED_RGBA_ASTC_12x10_KHR                       = 0x93BC;
+    public static final int GL_COMPRESSED_RGBA_ASTC_12x12_KHR                       = 0x93BD;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR                 = 0x93D0;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR                 = 0x93D1;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR                 = 0x93D2;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR                 = 0x93D3;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR                 = 0x93D4;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR                 = 0x93D5;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR                 = 0x93D6;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR                 = 0x93D7;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR                = 0x93D8;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR                = 0x93D9;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR                = 0x93DA;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR               = 0x93DB;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR               = 0x93DC;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR               = 0x93DD;
+
+    // GL_OES_sample_shading
+    public static final int GL_SAMPLE_SHADING_OES                                   = 0x8C36;
+    public static final int GL_MIN_SAMPLE_SHADING_VALUE_OES                         = 0x8C37;
+
+    // GL_OES_shader_multisample_interpolation
+    public static final int GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES                = 0x8E5B;
+    public static final int GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES                = 0x8E5C;
+    public static final int GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES               = 0x8E5D;
+
+    // GL_OES_texture_stencil8
+    public static final int GL_STENCIL_INDEX_OES                                    = 0x1901;
+    public static final int GL_STENCIL_INDEX8_OES                                   = 0x8D48;
+
+    // GL_OES_texture_storage_multisample_2d_array
+    public static final int GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES                     = 0x9102;
+    public static final int GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES             = 0x9105;
+    public static final int GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES                     = 0x910B;
+    public static final int GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES                 = 0x910C;
+    public static final int GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES        = 0x910D;
+
+    // GL_EXT_geometry_shader
+    public static final int GL_GEOMETRY_SHADER_EXT                                  = 0x8DD9;
+    public static final int GL_GEOMETRY_SHADER_BIT_EXT                              = 0x00000004;
+    public static final int GL_GEOMETRY_LINKED_VERTICES_OUT_EXT                     = 0x8916;
+    public static final int GL_GEOMETRY_LINKED_INPUT_TYPE_EXT                       = 0x8917;
+    public static final int GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT                      = 0x8918;
+    public static final int GL_GEOMETRY_SHADER_INVOCATIONS_EXT                      = 0x887F;
+    public static final int GL_LAYER_PROVOKING_VERTEX_EXT                           = 0x825E;
+    public static final int GL_LINES_ADJACENCY_EXT                                  = 0x000A;
+    public static final int GL_LINE_STRIP_ADJACENCY_EXT                             = 0x000B;
+    public static final int GL_TRIANGLES_ADJACENCY_EXT                              = 0x000C;
+    public static final int GL_TRIANGLE_STRIP_ADJACENCY_EXT                         = 0x000D;
+    public static final int GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT                  = 0x8DDF;
+    public static final int GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT                      = 0x8A2C;
+    public static final int GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT         = 0x8A32;
+    public static final int GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT                    = 0x9123;
+    public static final int GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT                   = 0x9124;
+    public static final int GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT                     = 0x8DE0;
+    public static final int GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT             = 0x8DE1;
+    public static final int GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT                  = 0x8E5A;
+    public static final int GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT                 = 0x8C29;
+    public static final int GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT              = 0x92CF;
+    public static final int GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT                     = 0x92D5;
+    public static final int GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT                      = 0x90CD;
+    public static final int GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT               = 0x90D7;
+    public static final int GL_FIRST_VERTEX_CONVENTION_EXT                          = 0x8E4D;
+    public static final int GL_LAST_VERTEX_CONVENTION_EXT                           = 0x8E4E;
+    public static final int GL_UNDEFINED_VERTEX_EXT                                 = 0x8260;
+    public static final int GL_PRIMITIVES_GENERATED_EXT                             = 0x8C87;
+    public static final int GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT                       = 0x9312;
+    public static final int GL_MAX_FRAMEBUFFER_LAYERS_EXT                           = 0x9317;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT             = 0x8DA8;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT                   = 0x8DA7;
+    public static final int GL_REFERENCED_BY_GEOMETRY_SHADER_EXT                    = 0x9309;
+
+    // GL_EXT_primitive_bounding_box
+    public static final int GL_PRIMITIVE_BOUNDING_BOX_EXT                           = 0x92BE;
+
+    // GL_EXT_tessellation_shader
+    public static final int GL_PATCHES_EXT                                          = 0x000E;
+    public static final int GL_PATCH_VERTICES_EXT                                   = 0x8E72;
+    public static final int GL_TESS_CONTROL_OUTPUT_VERTICES_EXT                     = 0x8E75;
+    public static final int GL_TESS_GEN_MODE_EXT                                    = 0x8E76;
+    public static final int GL_TESS_GEN_SPACING_EXT                                 = 0x8E77;
+    public static final int GL_TESS_GEN_VERTEX_ORDER_EXT                            = 0x8E78;
+    public static final int GL_TESS_GEN_POINT_MODE_EXT                              = 0x8E79;
+    public static final int GL_ISOLINES_EXT                                         = 0x8E7A;
+    public static final int GL_QUADS_EXT                                            = 0x0007;
+    public static final int GL_FRACTIONAL_ODD_EXT                                   = 0x8E7B;
+    public static final int GL_FRACTIONAL_EVEN_EXT                                  = 0x8E7C;
+    public static final int GL_MAX_PATCH_VERTICES_EXT                               = 0x8E7D;
+    public static final int GL_MAX_TESS_GEN_LEVEL_EXT                               = 0x8E7E;
+    public static final int GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT              = 0x8E7F;
+    public static final int GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT           = 0x8E80;
+    public static final int GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT             = 0x8E81;
+    public static final int GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT          = 0x8E82;
+    public static final int GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT               = 0x8E83;
+    public static final int GL_MAX_TESS_PATCH_COMPONENTS_EXT                        = 0x8E84;
+    public static final int GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT         = 0x8E85;
+    public static final int GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT            = 0x8E86;
+    public static final int GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT                  = 0x8E89;
+    public static final int GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT               = 0x8E8A;
+    public static final int GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT                = 0x886C;
+    public static final int GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT             = 0x886D;
+    public static final int GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT     = 0x8E1E;
+    public static final int GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT  = 0x8E1F;
+    public static final int GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT          = 0x92CD;
+    public static final int GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT       = 0x92CE;
+    public static final int GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT                 = 0x92D3;
+    public static final int GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT              = 0x92D4;
+    public static final int GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT                  = 0x90CB;
+    public static final int GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT               = 0x90CC;
+    public static final int GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT           = 0x90D8;
+    public static final int GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT        = 0x90D9;
+    public static final int GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED              = 0x8221;
+    public static final int GL_IS_PER_PATCH_EXT                                     = 0x92E7;
+    public static final int GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT                = 0x9307;
+    public static final int GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT             = 0x9308;
+    public static final int GL_TESS_CONTROL_SHADER_EXT                              = 0x8E88;
+    public static final int GL_TESS_EVALUATION_SHADER_EXT                           = 0x8E87;
+    public static final int GL_TESS_CONTROL_SHADER_BIT_EXT                          = 0x00000008;
+    public static final int GL_TESS_EVALUATION_SHADER_BIT_EXT                       = 0x00000010;
+
+    // GL_EXT_texture_border_clamp
+    public static final int GL_TEXTURE_BORDER_COLOR_EXT                             = 0x1004;
+    public static final int GL_CLAMP_TO_BORDER_EXT                                  = 0x812D;
+
+    // GL_EXT_texture_buffer
+    public static final int GL_TEXTURE_BUFFER_EXT                                   = 0x8C2A;
+    public static final int GL_TEXTURE_BUFFER_BINDING_EXT                           = 0x8C2A;
+    public static final int GL_MAX_TEXTURE_BUFFER_SIZE_EXT                          = 0x8C2B;
+    public static final int GL_TEXTURE_BINDING_BUFFER_EXT                           = 0x8C2C;
+    public static final int GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT                = 0x8C2D;
+    public static final int GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT                  = 0x919F;
+    public static final int GL_SAMPLER_BUFFER_EXT                                   = 0x8DC2;
+    public static final int GL_INT_SAMPLER_BUFFER_EXT                               = 0x8DD0;
+    public static final int GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT                      = 0x8DD8;
+    public static final int GL_IMAGE_BUFFER_EXT                                     = 0x9051;
+    public static final int GL_INT_IMAGE_BUFFER_EXT                                 = 0x905C;
+    public static final int GL_UNSIGNED_INT_IMAGE_BUFFER_EXT                        = 0x9067;
+    public static final int GL_TEXTURE_BUFFER_OFFSET_EXT                            = 0x919D;
+    public static final int GL_TEXTURE_BUFFER_SIZE_EXT                              = 0x919E;
+
+    // GL_EXT_texture_cube_map_array
+    public static final int GL_TEXTURE_CUBE_MAP_ARRAY_EXT                           = 0x9009;
+    public static final int GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT                   = 0x900A;
+    public static final int GL_SAMPLER_CUBE_MAP_ARRAY_EXT                           = 0x900C;
+    public static final int GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT                    = 0x900D;
+    public static final int GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT                       = 0x900E;
+    public static final int GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT              = 0x900F;
+    public static final int GL_IMAGE_CUBE_MAP_ARRAY_EXT                             = 0x9054;
+    public static final int GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT                         = 0x905F;
+    public static final int GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT                = 0x906A;
+
+    // GL_EXT_texture_sRGB_decode
+    public static final int GL_TEXTURE_SRGB_DECODE_EXT                              = 0x8A48;
+    public static final int GL_DECODE_EXT                                           = 0x8A49;
+    public static final int GL_SKIP_DECODE_EXT                                      = 0x8A4A;
+
+    native private static void _nativeClassInit();
+    static {
+        _nativeClassInit();
+    }
+
+    private GLES31Ext() {}
+    // C function void glBlendBarrierKHR ( void )
+
+    public static native void glBlendBarrierKHR(
+    );
+
+    // C function void glDebugMessageControlKHR ( GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled )
+
+    public static native void glDebugMessageControlKHR(
+        int source,
+        int type,
+        int severity,
+        int count,
+        int[] ids,
+        int offset,
+        boolean enabled
+    );
+
+    // C function void glDebugMessageControlKHR ( GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled )
+
+    public static native void glDebugMessageControlKHR(
+        int source,
+        int type,
+        int severity,
+        int count,
+        java.nio.IntBuffer ids,
+        boolean enabled
+    );
+
+    // C function void glDebugMessageInsertKHR ( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf )
+
+    public static native void glDebugMessageInsertKHR(
+        int source,
+        int type,
+        int id,
+        int severity,
+        String buf
+    );
+
+    // C function void glDebugMessageCallbackKHR ( GLDEBUGPROCKHR callback, const void *userParam )
+
+    public interface DebugProcKHR {
+        void onMessage(int source, int type, int id, int severity, String message);
+    }
+
+    public static native void glDebugMessageCallbackKHR(DebugProcKHR callback);
+
+    // C function GLuint glGetDebugMessageLogKHR ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog )
+
+    public static native int glGetDebugMessageLogKHR(
+        int count,
+        int bufSize,
+        int[] sources,
+        int sourcesOffset,
+        int[] types,
+        int typesOffset,
+        int[] ids,
+        int idsOffset,
+        int[] severities,
+        int severitiesOffset,
+        int[] lengths,
+        int lengthsOffset,
+        byte[] messageLog,
+        int messageLogOffset);
+
+    // C function GLuint glGetDebugMessageLogKHR ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog )
+
+    public static native int glGetDebugMessageLogKHR(
+        int count,
+        java.nio.IntBuffer sources,
+        java.nio.IntBuffer types,
+        java.nio.IntBuffer ids,
+        java.nio.IntBuffer severities,
+        java.nio.IntBuffer lengths,
+        java.nio.ByteBuffer messageLog);
+
+    // C function GLuint glGetDebugMessageLogKHR ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog )
+
+    public static native String[] glGetDebugMessageLogKHR(
+        int count,
+        int[] sources,
+        int sourcesOffset,
+        int[] types,
+        int typesOffset,
+        int[] ids,
+        int idsOffset,
+        int[] severities,
+        int severitiesOffset);
+
+    // C function GLuint glGetDebugMessageLogKHR ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog )
+
+    public static native String[] glGetDebugMessageLogKHR(
+        int count,
+        java.nio.IntBuffer sources,
+        java.nio.IntBuffer types,
+        java.nio.IntBuffer ids,
+        java.nio.IntBuffer severities);
+
+    // C function void glPushDebugGroupKHR ( GLenum source, GLuint id, GLsizei length, const GLchar *message )
+
+    public static native void glPushDebugGroupKHR(
+        int source,
+        int id,
+        int length,
+        String message
+    );
+
+    // C function void glPopDebugGroupKHR ( void )
+
+    public static native void glPopDebugGroupKHR(
+    );
+
+    // C function void glObjectLabelKHR ( GLenum identifier, GLuint name, GLsizei length, const GLchar *label )
+
+    public static native void glObjectLabelKHR(
+        int identifier,
+        int name,
+        int length,
+        String label
+    );
+
+    // C function void glGetObjectLabelKHR ( GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label )
+
+    public static native String glGetObjectLabelKHR(int identifier, int name);
+
+    // C function void glObjectPtrLabelKHR ( const void *ptr, GLsizei length, const GLchar *label )
+
+    public static native void glObjectPtrLabelKHR(long ptr, String label);
+
+    // C function void glGetObjectPtrLabelKHR ( const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label )
+
+    public static native String glGetObjectPtrLabelKHR(long ptr);
+
+    // C function void glGetPointervKHR ( GLenum pname, void **params )
+
+    public static native DebugProcKHR glGetDebugMessageCallbackKHR();
+
+    // C function void glMinSampleShadingOES ( GLfloat value )
+
+    public static native void glMinSampleShadingOES(
+        float value
+    );
+
+    // C function void glTexStorage3DMultisampleOES ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations )
+
+    public static native void glTexStorage3DMultisampleOES(
+        int target,
+        int samples,
+        int internalformat,
+        int width,
+        int height,
+        int depth,
+        boolean fixedsamplelocations
+    );
+
+    // C function void glCopyImageSubDataEXT ( GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth )
+
+    public static native void glCopyImageSubDataEXT(
+        int srcName,
+        int srcTarget,
+        int srcLevel,
+        int srcX,
+        int srcY,
+        int srcZ,
+        int dstName,
+        int dstTarget,
+        int dstLevel,
+        int dstX,
+        int dstY,
+        int dstZ,
+        int srcWidth,
+        int srcHeight,
+        int srcDepth
+    );
+
+    // C function void glEnableiEXT ( GLenum target, GLuint index )
+
+    public static native void glEnableiEXT(
+        int target,
+        int index
+    );
+
+    // C function void glDisableiEXT ( GLenum target, GLuint index )
+
+    public static native void glDisableiEXT(
+        int target,
+        int index
+    );
+
+    // C function void glBlendEquationiEXT ( GLuint buf, GLenum mode )
+
+    public static native void glBlendEquationiEXT(
+        int buf,
+        int mode
+    );
+
+    // C function void glBlendEquationSeparateiEXT ( GLuint buf, GLenum modeRGB, GLenum modeAlpha )
+
+    public static native void glBlendEquationSeparateiEXT(
+        int buf,
+        int modeRGB,
+        int modeAlpha
+    );
+
+    // C function void glBlendFunciEXT ( GLuint buf, GLenum src, GLenum dst )
+
+    public static native void glBlendFunciEXT(
+        int buf,
+        int src,
+        int dst
+    );
+
+    // C function void glBlendFuncSeparateiEXT ( GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha )
+
+    public static native void glBlendFuncSeparateiEXT(
+        int buf,
+        int srcRGB,
+        int dstRGB,
+        int srcAlpha,
+        int dstAlpha
+    );
+
+    // C function void glColorMaskiEXT ( GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a )
+
+    public static native void glColorMaskiEXT(
+        int index,
+        boolean r,
+        boolean g,
+        boolean b,
+        boolean a
+    );
+
+    // C function GLboolean glIsEnablediEXT ( GLenum target, GLuint index )
+
+    public static native boolean glIsEnablediEXT(
+        int target,
+        int index
+    );
+
+    // C function void glFramebufferTextureEXT ( GLenum target, GLenum attachment, GLuint texture, GLint level )
+
+    public static native void glFramebufferTextureEXT(
+        int target,
+        int attachment,
+        int texture,
+        int level
+    );
+
+    // C function void glPrimitiveBoundingBoxEXT ( GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW )
+
+    public static native void glPrimitiveBoundingBoxEXT(
+        float minX,
+        float minY,
+        float minZ,
+        float minW,
+        float maxX,
+        float maxY,
+        float maxZ,
+        float maxW
+    );
+
+    // C function void glPatchParameteriEXT ( GLenum pname, GLint value )
+
+    public static native void glPatchParameteriEXT(
+        int pname,
+        int value
+    );
+
+    // C function void glTexParameterIivEXT ( GLenum target, GLenum pname, const GLint *params )
+
+    public static native void glTexParameterIivEXT(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glTexParameterIivEXT ( GLenum target, GLenum pname, const GLint *params )
+
+    public static native void glTexParameterIivEXT(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glTexParameterIuivEXT ( GLenum target, GLenum pname, const GLuint *params )
+
+    public static native void glTexParameterIuivEXT(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glTexParameterIuivEXT ( GLenum target, GLenum pname, const GLuint *params )
+
+    public static native void glTexParameterIuivEXT(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetTexParameterIivEXT ( GLenum target, GLenum pname, GLint *params )
+
+    public static native void glGetTexParameterIivEXT(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetTexParameterIivEXT ( GLenum target, GLenum pname, GLint *params )
+
+    public static native void glGetTexParameterIivEXT(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetTexParameterIuivEXT ( GLenum target, GLenum pname, GLuint *params )
+
+    public static native void glGetTexParameterIuivEXT(
+        int target,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetTexParameterIuivEXT ( GLenum target, GLenum pname, GLuint *params )
+
+    public static native void glGetTexParameterIuivEXT(
+        int target,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glSamplerParameterIivEXT ( GLuint sampler, GLenum pname, const GLint *param )
+
+    public static native void glSamplerParameterIivEXT(
+        int sampler,
+        int pname,
+        int[] param,
+        int offset
+    );
+
+    // C function void glSamplerParameterIivEXT ( GLuint sampler, GLenum pname, const GLint *param )
+
+    public static native void glSamplerParameterIivEXT(
+        int sampler,
+        int pname,
+        java.nio.IntBuffer param
+    );
+
+    // C function void glSamplerParameterIuivEXT ( GLuint sampler, GLenum pname, const GLuint *param )
+
+    public static native void glSamplerParameterIuivEXT(
+        int sampler,
+        int pname,
+        int[] param,
+        int offset
+    );
+
+    // C function void glSamplerParameterIuivEXT ( GLuint sampler, GLenum pname, const GLuint *param )
+
+    public static native void glSamplerParameterIuivEXT(
+        int sampler,
+        int pname,
+        java.nio.IntBuffer param
+    );
+
+    // C function void glGetSamplerParameterIivEXT ( GLuint sampler, GLenum pname, GLint *params )
+
+    public static native void glGetSamplerParameterIivEXT(
+        int sampler,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetSamplerParameterIivEXT ( GLuint sampler, GLenum pname, GLint *params )
+
+    public static native void glGetSamplerParameterIivEXT(
+        int sampler,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glGetSamplerParameterIuivEXT ( GLuint sampler, GLenum pname, GLuint *params )
+
+    public static native void glGetSamplerParameterIuivEXT(
+        int sampler,
+        int pname,
+        int[] params,
+        int offset
+    );
+
+    // C function void glGetSamplerParameterIuivEXT ( GLuint sampler, GLenum pname, GLuint *params )
+
+    public static native void glGetSamplerParameterIuivEXT(
+        int sampler,
+        int pname,
+        java.nio.IntBuffer params
+    );
+
+    // C function void glTexBufferEXT ( GLenum target, GLenum internalformat, GLuint buffer )
+
+    public static native void glTexBufferEXT(
+        int target,
+        int internalformat,
+        int buffer
+    );
+
+    // C function void glTexBufferRangeEXT ( GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size )
+
+    public static native void glTexBufferRangeEXT(
+        int target,
+        int internalformat,
+        int buffer,
+        int offset,
+        int size
+    );
+
+}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 16fc3e5..d388ab7 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -35,6 +35,7 @@
 import android.provider.DocumentsContract.Document;
 import android.provider.DocumentsContract.Root;
 import android.provider.DocumentsProvider;
+import android.text.TextUtils;
 import android.util.Log;
 import android.webkit.MimeTypeMap;
 
@@ -239,9 +240,12 @@
         if (file.canWrite()) {
             if (file.isDirectory()) {
                 flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
+                flags |= Document.FLAG_SUPPORTS_DELETE;
+                flags |= Document.FLAG_SUPPORTS_RENAME;
             } else {
                 flags |= Document.FLAG_SUPPORTS_WRITE;
                 flags |= Document.FLAG_SUPPORTS_DELETE;
+                flags |= Document.FLAG_SUPPORTS_RENAME;
             }
         }
 
@@ -332,9 +336,29 @@
     }
 
     @Override
+    public String renameDocument(String docId, String displayName) throws FileNotFoundException {
+        final File before = getFileForDocId(docId);
+        final File after = new File(before.getParentFile(), displayName);
+        if (after.exists()) {
+            throw new IllegalStateException("Already exists " + after);
+        }
+        if (!before.renameTo(after)) {
+            throw new IllegalStateException("Failed to rename to " + after);
+        }
+        final String afterDocId = getDocIdForFile(after);
+        if (!TextUtils.equals(docId, afterDocId)) {
+            return afterDocId;
+        } else {
+            return null;
+        }
+    }
+
+    @Override
     public void deleteDocument(String docId) throws FileNotFoundException {
-        // TODO: extend to delete directories
         final File file = getFileForDocId(docId);
+        if (file.isDirectory()) {
+            FileUtils.deleteContents(file);
+        }
         if (!file.delete()) {
             throw new IllegalStateException("Failed to delete " + file);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index e699dd9..457d32e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -446,9 +446,25 @@
                         com.android.internal.R.drawable.notification_bg,
                         com.android.internal.R.drawable.notification_bg_dim);
             }
+        } else {
+            // Using platform templates
+            final int color = sbn.getNotification().color;
+            if (isMediaNotification(entry)) {
+                entry.row.setBackgroundResourceIds(
+                        com.android.internal.R.drawable.notification_quantum_bg,
+                        color,
+                        com.android.internal.R.drawable.notification_quantum_bg_dim,
+                        color);
+            }
         }
     }
 
+    private boolean isMediaNotification(NotificationData.Entry entry) {
+        // TODO: confirm that there's a valid media key
+        return entry.expandedBig != null &&
+               entry.expandedBig.findViewById(com.android.internal.R.id.media_action_area) != null;
+    }
+
     private void startApplicationDetailsActivity(String packageName) {
         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                 Uri.fromParts("package", packageName, null));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 6b6f55a..b1a5750 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -36,7 +36,7 @@
         public View expanded; // the inflated RemoteViews
         public View expandedPublic; // for insecure lockscreens
         public ImageView largeIcon;
-        private View expandedBig;
+        public View expandedBig;
         private boolean interruption;
         public Entry() {}
         public Entry(IBinder key, StatusBarNotification n, StatusBarIconView ic) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index 36b063b..389e725 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -87,6 +87,16 @@
                 (ToggleSlider) findViewById(R.id.brightness_slider));
         loadDimens();
         updateVisibilities();
+        addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right,
+                    int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                if ((right - left) != (oldRight - oldLeft)) {
+                    // width changed, update clipping
+                    setClipping(getHeight());
+                }
+            }
+        });
     }
 
     private void loadDimens() {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 55ae9c6..de46b16 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -130,6 +130,8 @@
             "com.android.server.wifi.p2p.WifiP2pService";
     private static final String HDMI_CEC_SERVICE_CLASS =
             "com.android.server.hdmi.HdmiCecService";
+    private static final String ETHERNET_SERVICE_CLASS =
+            "com.android.server.ethernet.EthernetService";
 
     private final int mFactoryTestMode;
     private Timer mProfilerSnapshotTimer;
@@ -660,6 +662,12 @@
                 }
 
                 try {
+                    mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
+                } catch (Throwable e) {
+                    reportWtf("starting Ethernet Service", e);
+                }
+
+                try {
                     Slog.i(TAG, "Connectivity Service");
                     connectivity = new ConnectivityService(
                             context, networkManagement, networkStats, networkPolicy);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index f5cf978..bafc71e 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -306,6 +306,12 @@
 
     /**
      * @hide
+     * last failure
+     */
+    public String lastFailure;
+
+    /**
+     * @hide
      * BSSID list on which this configuration was seen.
      * TODO: prevent this list to grow infinitely, age-out the results
      */
@@ -910,6 +916,8 @@
             if (source.visibility != null) {
                 visibility = new Visibility(source.visibility);
             }
+
+            lastFailure = source.lastFailure;
         }
     }