Fix wallpaper placement + performance improvement

Wallpaper would have the wrong placement during
first frame because it would be center aligned
in a surface that's not big enough.

Also removed old OpenGl implementation, in favor of new
hardware accelerated canvas.

Change-Id: Ic9c9eaa817e1f6494aa5431d8278f2c28b2c45a9
Fixes: 66926914
Test: set wallpapaer with different offsets, orientations and devices
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 942cc99..081bd81 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -388,11 +388,12 @@
 
         public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
                 @SetWallpaperFlags int which) {
-            return peekWallpaperBitmap(context, returnDefault, which, context.getUserId());
+            return peekWallpaperBitmap(context, returnDefault, which, context.getUserId(),
+                    false /* hardware */);
         }
 
         public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault,
-                @SetWallpaperFlags int which, int userId) {
+                @SetWallpaperFlags int which, int userId, boolean hardware) {
             if (mService != null) {
                 try {
                     if (!mService.isWallpaperSupported(context.getOpPackageName())) {
@@ -409,7 +410,7 @@
                 mCachedWallpaper = null;
                 mCachedWallpaperUserId = 0;
                 try {
-                    mCachedWallpaper = getCurrentWallpaperLocked(context, userId);
+                    mCachedWallpaper = getCurrentWallpaperLocked(context, userId, hardware);
                     mCachedWallpaperUserId = userId;
                 } catch (OutOfMemoryError e) {
                     Log.w(TAG, "Out of memory loading the current wallpaper: " + e);
@@ -447,7 +448,7 @@
             }
         }
 
-        private Bitmap getCurrentWallpaperLocked(Context context, int userId) {
+        private Bitmap getCurrentWallpaperLocked(Context context, int userId, boolean hardware) {
             if (mService == null) {
                 Log.w(TAG, "WallpaperService not running");
                 return null;
@@ -460,6 +461,9 @@
                 if (fd != null) {
                     try {
                         BitmapFactory.Options options = new BitmapFactory.Options();
+                        if (hardware) {
+                            options.inPreferredConfig = Bitmap.Config.HARDWARE;
+                        }
                         return BitmapFactory.decodeFileDescriptor(
                                 fd.getFileDescriptor(), null, options);
                     } catch (OutOfMemoryError e) {
@@ -814,12 +818,23 @@
     }
 
     /**
-     * Like {@link #getDrawable()} but returns a Bitmap.
+     * Like {@link #getDrawable()} but returns a Bitmap with default {@link Bitmap.Config}.
      *
      * @hide
      */
     public Bitmap getBitmap() {
-        return getBitmapAsUser(mContext.getUserId());
+        return getBitmap(false);
+    }
+
+    /**
+     * Like {@link #getDrawable()} but returns a Bitmap.
+     *
+     * @param hardware Asks for a hardware backed bitmap.
+     * @see Bitmap.Config#HARDWARE
+     * @hide
+     */
+    public Bitmap getBitmap(boolean hardware) {
+        return getBitmapAsUser(mContext.getUserId(), hardware);
     }
 
     /**
@@ -827,8 +842,8 @@
      *
      * @hide
      */
-    public Bitmap getBitmapAsUser(int userId) {
-        return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId);
+    public Bitmap getBitmapAsUser(int userId, boolean hardware) {
+        return sGlobals.peekWallpaperBitmap(mContext, true, FLAG_SYSTEM, userId, hardware);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 907a79e..593bb50 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -16,11 +16,6 @@
 
 package com.android.systemui;
 
-import static android.opengl.GLES20.*;
-
-import static javax.microedition.khronos.egl.EGL10.*;
-
-import android.app.ActivityManager;
 import android.app.WallpaperManager;
 import android.content.ComponentCallbacks2;
 import android.graphics.Bitmap;
@@ -28,31 +23,18 @@
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.Region.Op;
-import android.opengl.GLUtils;
 import android.os.AsyncTask;
-import android.os.SystemProperties;
 import android.os.Trace;
-import android.renderscript.Matrix4f;
 import android.service.wallpaper.WallpaperService;
 import android.util.Log;
 import android.view.Display;
 import android.view.DisplayInfo;
-import android.view.MotionEvent;
 import android.view.SurfaceHolder;
 import android.view.WindowManager;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
 
 /**
  * Default built-in wallpaper that simply shows a static image.
@@ -64,24 +46,13 @@
     private static final boolean DEBUG = false;
     private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu";
 
-    static final boolean FIXED_SIZED_SURFACE = true;
-    static final boolean USE_OPENGL = true;
-
-    WallpaperManager mWallpaperManager;
-
-    DrawableEngine mEngine;
-
-    boolean mIsHwAccelerated;
+    private WallpaperManager mWallpaperManager;
+    private DrawableEngine mEngine;
 
     @Override
     public void onCreate() {
         super.onCreate();
-        mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
-
-        //noinspection PointlessBooleanExpression,ConstantConditions
-        if (FIXED_SIZED_SURFACE && USE_OPENGL) {
-            mIsHwAccelerated = ActivityManager.isHighEndGfx();
-        }
+        mWallpaperManager = getSystemService(WallpaperManager.class);
     }
 
     @Override
@@ -98,15 +69,12 @@
     }
 
     class DrawableEngine extends Engine {
-        static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
-        static final int EGL_OPENGL_ES2_BIT = 4;
-
         Bitmap mBackground;
         int mBackgroundWidth = -1, mBackgroundHeight = -1;
         int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
         int mLastRotation = -1;
-        float mXOffset = 0.5f;
-        float mYOffset = 0.5f;
+        float mXOffset = 0f;
+        float mYOffset = 0f;
         float mScale = 1f;
 
         private Display mDefaultDisplay;
@@ -117,34 +85,6 @@
         int mLastXTranslation;
         int mLastYTranslation;
 
-        private EGL10 mEgl;
-        private EGLDisplay mEglDisplay;
-        private EGLConfig mEglConfig;
-        private EGLContext mEglContext;
-        private EGLSurface mEglSurface;
-
-        private static final String sSimpleVS =
-                "attribute vec4 position;\n" +
-                "attribute vec2 texCoords;\n" +
-                "varying vec2 outTexCoords;\n" +
-                "uniform mat4 projection;\n" +
-                "\nvoid main(void) {\n" +
-                "    outTexCoords = texCoords;\n" +
-                "    gl_Position = projection * position;\n" +
-                "}\n\n";
-        private static final String sSimpleFS =
-                "precision mediump float;\n\n" +
-                "varying vec2 outTexCoords;\n" +
-                "uniform sampler2D texture;\n" +
-                "\nvoid main(void) {\n" +
-                "    gl_FragColor = texture2D(texture, outTexCoords);\n" +
-                "}\n\n";
-
-        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 int mRotationAtLastSurfaceSizeUpdate = -1;
         private int mDisplayWidthAtLastSurfaceSizeUpdate = -1;
         private int mDisplayHeightAtLastSurfaceSizeUpdate = -1;
@@ -154,13 +94,14 @@
         private AsyncTask<Void, Void, Bitmap> mLoader;
         private boolean mNeedsDrawAfterLoadingWallpaper;
         private boolean mSurfaceValid;
+        private boolean mSurfaceRedrawNeeded;
 
-        public DrawableEngine() {
+        DrawableEngine() {
             super();
             setFixedSizeAllowed(true);
         }
 
-        public void trimMemory(int level) {
+        void trimMemory(int level) {
             if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW
                     && level <= ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL
                     && mBackground != null) {
@@ -179,6 +120,7 @@
 
             super.onCreate(surfaceHolder);
 
+            //noinspection ConstantConditions
             mDefaultDisplay = getSystemService(WindowManager.class).getDefaultDisplay();
             setOffsetNotificationsEnabled(false);
 
@@ -199,7 +141,7 @@
             // Load background image dimensions, if we haven't saved them yet
             if (mBackgroundWidth <= 0 || mBackgroundHeight <= 0) {
                 // Need to load the image to get dimensions
-                loadWallpaper(forDraw, false /* needsReset */);
+                loadWallpaper(forDraw);
                 if (DEBUG) {
                     Log.d(TAG, "Reloading, redoing updateSurfaceSize later.");
                 }
@@ -210,16 +152,13 @@
             int surfaceWidth = Math.max(displayInfo.logicalWidth, mBackgroundWidth);
             int surfaceHeight = Math.max(displayInfo.logicalHeight, mBackgroundHeight);
 
-            if (FIXED_SIZED_SURFACE) {
-                // Used a fixed size surface, because we are special.  We can do
-                // this because we know the current design of window animations doesn't
-                // cause this to break.
-                surfaceHolder.setFixedSize(surfaceWidth, surfaceHeight);
-                mLastRequestedWidth = surfaceWidth;
-                mLastRequestedHeight = surfaceHeight;
-            } else {
-                surfaceHolder.setSizeFromLayout();
-            }
+            // Used a fixed size surface, because we are special.  We can do
+            // this because we know the current design of window animations doesn't
+            // cause this to break.
+            surfaceHolder.setFixedSize(surfaceWidth, surfaceHeight);
+            mLastRequestedWidth = surfaceWidth;
+            mLastRequestedHeight = surfaceHeight;
+
             return hasWallpaper;
         }
 
@@ -300,6 +239,13 @@
                 Log.d(TAG, "onSurfaceRedrawNeeded");
             }
             super.onSurfaceRedrawNeeded(holder);
+            // At the end of this method we should have drawn into the surface.
+            // This means that the bitmap should be loaded synchronously if
+            // it was already unloaded.
+            if (mBackground == null) {
+                updateBitmap(mWallpaperManager.getBitmap(true /* hardware */));
+            }
+            mSurfaceRedrawNeeded = true;
             drawFrame();
         }
 
@@ -336,7 +282,8 @@
                 boolean surfaceDimensionsChanged = dw != mLastSurfaceWidth
                         || dh != mLastSurfaceHeight;
 
-                boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation;
+                boolean redrawNeeded = surfaceDimensionsChanged || newRotation != mLastRotation
+                        || mSurfaceRedrawNeeded;
                 if (!redrawNeeded && !mOffsetsChanged) {
                     if (DEBUG) {
                         Log.d(TAG, "Suppressed drawFrame since redraw is not needed "
@@ -345,40 +292,24 @@
                     return;
                 }
                 mLastRotation = newRotation;
+                mSurfaceRedrawNeeded = false;
 
                 // Load bitmap if it is not yet loaded
                 if (mBackground == null) {
-                    if (DEBUG) {
-                        Log.d(TAG, "Reloading bitmap: mBackground, bgw, bgh, dw, dh = " +
-                                mBackground + ", " +
-                                ((mBackground == null) ? 0 : mBackground.getWidth()) + ", " +
-                                ((mBackground == null) ? 0 : mBackground.getHeight()) + ", " +
-                                dw + ", " + dh);
-                    }
-                    loadWallpaper(true /* needDraw */, true /* needReset */);
+                    loadWallpaper(true);
                     if (DEBUG) {
                         Log.d(TAG, "Reloading, resuming draw later");
                     }
                     return;
                 }
 
-                // Center the scaled image
+                // Left align the scaled image
                 mScale = Math.max(1f, Math.max(dw / (float) mBackground.getWidth(),
                         dh / (float) mBackground.getHeight()));
-                final int availw = dw - (int) (mBackground.getWidth() * mScale);
-                final int availh = dh - (int) (mBackground.getHeight() * mScale);
-                int xPixels = availw / 2;
-                int yPixels = availh / 2;
-
-                // Adjust the image for xOffset/yOffset values. If window manager is handling offsets,
-                // mXOffset and mYOffset are set to 0.5f by default and therefore xPixels and yPixels
-                // will remain unchanged
-                final int availwUnscaled = dw - mBackground.getWidth();
-                final int availhUnscaled = dh - mBackground.getHeight();
-                if (availwUnscaled < 0)
-                    xPixels += (int) (availwUnscaled * (mXOffset - .5f) + .5f);
-                if (availhUnscaled < 0)
-                    yPixels += (int) (availhUnscaled * (mYOffset - .5f) + .5f);
+                final int availw = (int) (mBackground.getWidth() * mScale) - dw;
+                final int availh = (int) (mBackground.getHeight() * mScale) - dh;
+                int xPixels = (int) (availw * mXOffset);
+                int yPixels = (int) (availh * mYOffset);
 
                 mOffsetsChanged = false;
                 if (surfaceDimensionsChanged) {
@@ -399,21 +330,7 @@
                     Log.d(TAG, "Redrawing wallpaper");
                 }
 
-                if (mIsHwAccelerated) {
-                    if (!drawWallpaperWithOpenGL(sh, availw, availh, xPixels, yPixels)) {
-                        drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
-                    }
-                } else {
-                    drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
-                    if (FIXED_SIZED_SURFACE) {
-                        // If the surface is fixed-size, we should only need to
-                        // draw it once and then we'll let the window manager
-                        // position it appropriately.  As such, we no longer needed
-                        // the loaded bitmap.  Yay!
-                        // hw-accelerated renderer retains bitmap for faster rotation
-                        unloadWallpaper(false /* forgetSize */);
-                    }
-                }
+                drawWallpaperWithCanvas(sh, availw, availh, xPixels, yPixels);
             } finally {
                 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
             }
@@ -428,28 +345,20 @@
          *
          * If {@param needsReset} is set also clears the cache in WallpaperManager first.
          */
-        private void loadWallpaper(boolean needsDraw, boolean needsReset) {
+        private void loadWallpaper(boolean needsDraw) {
             mNeedsDrawAfterLoadingWallpaper |= needsDraw;
             if (mLoader != null) {
-                if (needsReset) {
-                    mLoader.cancel(false /* interrupt */);
-                    mLoader = null;
-                } else {
-                    if (DEBUG) {
-                        Log.d(TAG, "Skipping loadWallpaper, already in flight ");
-                    }
-                    return;
+                if (DEBUG) {
+                    Log.d(TAG, "Skipping loadWallpaper, already in flight ");
                 }
+                return;
             }
             mLoader = new AsyncTask<Void, Void, Bitmap>() {
                 @Override
                 protected Bitmap doInBackground(Void... params) {
                     Throwable exception;
                     try {
-                        if (needsReset) {
-                            mWallpaperManager.forgetLoadedWallpaper();
-                        }
-                        return mWallpaperManager.getBitmap();
+                        return mWallpaperManager.getBitmap(true /* hardware */);
                     } catch (RuntimeException | OutOfMemoryError e) {
                         exception = e;
                     }
@@ -458,48 +367,33 @@
                         return null;
                     }
 
-                    if (exception != null) {
-                        // Note that if we do fail at this, and the default wallpaper can't
-                        // be loaded, we will go into a cycle.  Don't do a build where the
-                        // default wallpaper can't be loaded.
-                        Log.w(TAG, "Unable to load wallpaper!", exception);
-                        try {
-                            mWallpaperManager.clear();
-                        } catch (IOException ex) {
-                            // now we're really screwed.
-                            Log.w(TAG, "Unable reset to default wallpaper!", ex);
-                        }
+                    // Note that if we do fail at this, and the default wallpaper can't
+                    // be loaded, we will go into a cycle.  Don't do a build where the
+                    // default wallpaper can't be loaded.
+                    Log.w(TAG, "Unable to load wallpaper!", exception);
+                    try {
+                        mWallpaperManager.clear();
+                    } catch (IOException ex) {
+                        // now we're really screwed.
+                        Log.w(TAG, "Unable reset to default wallpaper!", ex);
+                    }
 
-                        if (isCancelled()) {
-                            return null;
-                        }
+                    if (isCancelled()) {
+                        return null;
+                    }
 
-                        try {
-                            return mWallpaperManager.getBitmap();
-                        } catch (RuntimeException | OutOfMemoryError e) {
-                            Log.w(TAG, "Unable to load default wallpaper!", e);
-                        }
+                    try {
+                        return mWallpaperManager.getBitmap(true /* hardware */);
+                    } catch (RuntimeException | OutOfMemoryError e) {
+                        Log.w(TAG, "Unable to load default wallpaper!", e);
                     }
                     return null;
                 }
 
                 @Override
                 protected void onPostExecute(Bitmap b) {
-                    mBackground = null;
-                    mBackgroundWidth = -1;
-                    mBackgroundHeight = -1;
+                    updateBitmap(b);
 
-                    if (b != null) {
-                        mBackground = b;
-                        mBackgroundWidth = mBackground.getWidth();
-                        mBackgroundHeight = mBackground.getHeight();
-                    }
-
-                    if (DEBUG) {
-                        Log.d(TAG, "Wallpaper loaded: " + mBackground);
-                    }
-                    updateSurfaceSize(getSurfaceHolder(), getDefaultDisplayInfo(),
-                            false /* forDraw */);
                     if (mNeedsDrawAfterLoadingWallpaper) {
                         drawFrame();
                     }
@@ -510,6 +404,24 @@
             }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
         }
 
+        private void updateBitmap(Bitmap bitmap) {
+            mBackground = null;
+            mBackgroundWidth = -1;
+            mBackgroundHeight = -1;
+
+            if (bitmap != null) {
+                mBackground = bitmap;
+                mBackgroundWidth = mBackground.getWidth();
+                mBackgroundHeight = mBackground.getHeight();
+            }
+
+            if (DEBUG) {
+                Log.d(TAG, "Wallpaper loaded: " + mBackground);
+            }
+            updateSurfaceSize(getSurfaceHolder(), getDefaultDisplayInfo(),
+                    false /* forDraw */);
+        }
+
         private void unloadWallpaper(boolean forgetSize) {
             if (mLoader != null) {
                 mLoader.cancel(false);
@@ -564,7 +476,7 @@
         }
 
         private void drawWallpaperWithCanvas(SurfaceHolder sh, int w, int h, int left, int top) {
-            Canvas c = sh.lockCanvas();
+            Canvas c = sh.lockHardwareCanvas();
             if (c != null) {
                 try {
                     if (DEBUG) {
@@ -590,278 +502,5 @@
                 }
             }
         }
-
-        private boolean drawWallpaperWithOpenGL(SurfaceHolder sh, int w, int h, int left, int top) {
-            if (!initGL(sh)) return false;
-
-            final float right = left + mBackground.getWidth() * mScale;
-            final float bottom = top + mBackground.getHeight() * mScale;
-
-            final Rect frame = sh.getSurfaceFrame();
-            final Matrix4f ortho = new Matrix4f();
-            ortho.loadOrtho(0.0f, frame.width(), frame.height(), 0.0f, -1.0f, 1.0f);
-
-            final FloatBuffer triangleVertices = createMesh(left, top, right, bottom);
-
-            final int texture = loadTexture(mBackground);
-            final int program = buildProgram(sSimpleVS, sSimpleFS);
-
-            final int attribPosition = glGetAttribLocation(program, "position");
-            final int attribTexCoords = glGetAttribLocation(program, "texCoords");
-            final int uniformTexture = glGetUniformLocation(program, "texture");
-            final int uniformProjection = glGetUniformLocation(program, "projection");
-
-            checkGlError();
-
-            glViewport(0, 0, frame.width(), frame.height());
-            glBindTexture(GL_TEXTURE_2D, texture);
-
-            glUseProgram(program);
-            glEnableVertexAttribArray(attribPosition);
-            glEnableVertexAttribArray(attribTexCoords);
-            glUniform1i(uniformTexture, 0);
-            glUniformMatrix4fv(uniformProjection, 1, false, ortho.getArray(), 0);
-
-            checkGlError();
-
-            if (w > 0 || h > 0) {
-                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-                glClear(GL_COLOR_BUFFER_BIT);
-            }
-
-            // drawQuad
-            triangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
-            glVertexAttribPointer(attribPosition, 3, GL_FLOAT, false,
-                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
-
-            triangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
-            glVertexAttribPointer(attribTexCoords, 3, GL_FLOAT, false,
-                    TRIANGLE_VERTICES_DATA_STRIDE_BYTES, triangleVertices);
-
-            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
-            boolean status = mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
-            checkEglError();
-
-            finishGL(texture, program);
-
-            return status;
-        }
-
-        private FloatBuffer createMesh(int left, int top, float right, float bottom) {
-            final float[] verticesData = {
-                    // X, Y, Z, U, V
-                     left,  bottom, 0.0f, 0.0f, 1.0f,
-                     right, bottom, 0.0f, 1.0f, 1.0f,
-                     left,  top,    0.0f, 0.0f, 0.0f,
-                     right, top,    0.0f, 1.0f, 0.0f,
-            };
-
-            final int bytes = verticesData.length * FLOAT_SIZE_BYTES;
-            final FloatBuffer triangleVertices = ByteBuffer.allocateDirect(bytes).order(
-                    ByteOrder.nativeOrder()).asFloatBuffer();
-            triangleVertices.put(verticesData).position(0);
-            return triangleVertices;
-        }
-
-        private int loadTexture(Bitmap bitmap) {
-            int[] textures = new int[1];
-
-            glActiveTexture(GL_TEXTURE0);
-            glGenTextures(1, textures, 0);
-            checkGlError();
-
-            int texture = textures[0];
-            glBindTexture(GL_TEXTURE_2D, texture);
-            checkGlError();
-
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
-            GLUtils.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap, GL_UNSIGNED_BYTE, 0);
-            checkGlError();
-
-            return texture;
-        }
-
-        private int buildProgram(String vertex, String fragment) {
-            int vertexShader = buildShader(vertex, GL_VERTEX_SHADER);
-            if (vertexShader == 0) return 0;
-
-            int fragmentShader = buildShader(fragment, GL_FRAGMENT_SHADER);
-            if (fragmentShader == 0) return 0;
-
-            int program = glCreateProgram();
-            glAttachShader(program, vertexShader);
-            glAttachShader(program, fragmentShader);
-            glLinkProgram(program);
-            checkGlError();
-
-            glDeleteShader(vertexShader);
-            glDeleteShader(fragmentShader);
-
-            int[] status = new int[1];
-            glGetProgramiv(program, GL_LINK_STATUS, status, 0);
-            if (status[0] != GL_TRUE) {
-                String error = glGetProgramInfoLog(program);
-                Log.d(GL_LOG_TAG, "Error while linking program:\n" + error);
-                glDeleteProgram(program);
-                return 0;
-            }
-
-            return program;
-        }
-
-        private int buildShader(String source, int type) {
-            int shader = glCreateShader(type);
-
-            glShaderSource(shader, source);
-            checkGlError();
-
-            glCompileShader(shader);
-            checkGlError();
-
-            int[] status = new int[1];
-            glGetShaderiv(shader, GL_COMPILE_STATUS, status, 0);
-            if (status[0] != GL_TRUE) {
-                String error = glGetShaderInfoLog(shader);
-                Log.d(GL_LOG_TAG, "Error while compiling shader:\n" + error);
-                glDeleteShader(shader);
-                return 0;
-            }
-
-            return shader;
-        }
-
-        private void checkEglError() {
-            int error = mEgl.eglGetError();
-            if (error != EGL_SUCCESS) {
-                Log.w(GL_LOG_TAG, "EGL error = " + GLUtils.getEGLErrorString(error));
-            }
-        }
-
-        private void checkGlError() {
-            int error = glGetError();
-            if (error != GL_NO_ERROR) {
-                Log.w(GL_LOG_TAG, "GL error = 0x" + Integer.toHexString(error), new Throwable());
-            }
-        }
-
-        private void finishGL(int texture, int program) {
-            int[] textures = new int[1];
-            textures[0] = texture;
-            glDeleteTextures(1, textures, 0);
-            glDeleteProgram(program);
-            mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-            mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
-            mEgl.eglDestroyContext(mEglDisplay, mEglContext);
-            mEgl.eglTerminate(mEglDisplay);
-        }
-
-        private boolean initGL(SurfaceHolder surfaceHolder) {
-            mEgl = (EGL10) EGLContext.getEGL();
-
-            mEglDisplay = mEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-            if (mEglDisplay == EGL_NO_DISPLAY) {
-                throw new RuntimeException("eglGetDisplay failed " +
-                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
-            }
-
-            int[] version = new int[2];
-            if (!mEgl.eglInitialize(mEglDisplay, version)) {
-                throw new RuntimeException("eglInitialize failed " +
-                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
-            }
-
-            mEglConfig = chooseEglConfig();
-            if (mEglConfig == null) {
-                throw new RuntimeException("eglConfig not initialized");
-            }
-
-            mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
-            if (mEglContext == EGL_NO_CONTEXT) {
-                throw new RuntimeException("createContext failed " +
-                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
-            }
-
-            int attribs[] = {
-                EGL_WIDTH, 1,
-                EGL_HEIGHT, 1,
-                EGL_NONE
-            };
-            EGLSurface tmpSurface = mEgl.eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
-            mEgl.eglMakeCurrent(mEglDisplay, tmpSurface, tmpSurface, mEglContext);
-
-            int[] maxSize = new int[1];
-            Rect frame = surfaceHolder.getSurfaceFrame();
-            glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0);
-
-            mEgl.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-            mEgl.eglDestroySurface(mEglDisplay, tmpSurface);
-
-            if(frame.width() > maxSize[0] || frame.height() > maxSize[0]) {
-                mEgl.eglDestroyContext(mEglDisplay, mEglContext);
-                mEgl.eglTerminate(mEglDisplay);
-                Log.e(GL_LOG_TAG, "requested  texture size " +
-                    frame.width() + "x" + frame.height() + " exceeds the support maximum of " +
-                    maxSize[0] + "x" + maxSize[0]);
-                return false;
-            }
-
-            mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surfaceHolder, null);
-            if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
-                int error = mEgl.eglGetError();
-                if (error == EGL_BAD_NATIVE_WINDOW || error == EGL_BAD_ALLOC) {
-                    Log.e(GL_LOG_TAG, "createWindowSurface returned " +
-                                         GLUtils.getEGLErrorString(error) + ".");
-                    return false;
-                }
-                throw new RuntimeException("createWindowSurface failed " +
-                        GLUtils.getEGLErrorString(error));
-            }
-
-            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
-                throw new RuntimeException("eglMakeCurrent failed " +
-                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
-            }
-
-            return true;
-        }
-
-
-        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
-            int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
-            return egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attrib_list);
-        }
-
-        private EGLConfig chooseEglConfig() {
-            int[] configsCount = new int[1];
-            EGLConfig[] configs = new EGLConfig[1];
-            int[] configSpec = getConfig();
-            if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
-                throw new IllegalArgumentException("eglChooseConfig failed " +
-                        GLUtils.getEGLErrorString(mEgl.eglGetError()));
-            } else if (configsCount[0] > 0) {
-                return configs[0];
-            }
-            return null;
-        }
-
-        private int[] getConfig() {
-            return new int[] {
-                    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-                    EGL_RED_SIZE, 8,
-                    EGL_GREEN_SIZE, 8,
-                    EGL_BLUE_SIZE, 8,
-                    EGL_ALPHA_SIZE, 0,
-                    EGL_DEPTH_SIZE, 0,
-                    EGL_STENCIL_SIZE, 0,
-                    EGL_CONFIG_CAVEAT, EGL_NONE,
-                    EGL_NONE
-            };
-        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 87f5ca7..40ddf5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -124,8 +124,8 @@
         } else {
             if (selectedUser != null) {
                 // Show the selected user's static wallpaper.
-                return LoaderResult.success(
-                        mWallpaperManager.getBitmapAsUser(selectedUser.getIdentifier()));
+                return LoaderResult.success(mWallpaperManager.getBitmapAsUser(
+                        selectedUser.getIdentifier(), true /* hardware */));
 
             } else {
                 // When there is no selected user, show the system wallpaper