Merge "Fixing logic to determine if wallpaper change." into ub-launcher3-master
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index 4ad7b6a..05af94d 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -496,10 +496,9 @@
         if (lastPhoto != null) {
             ImageView galleryThumbnailBg =
                     (ImageView) pickImageTile.findViewById(R.id.wallpaper_image);
-            galleryThumbnailBg.setImageBitmap(getThumbnailOfLastPhoto());
+            galleryThumbnailBg.setImageBitmap(lastPhoto);
             int colorOverlay = getResources().getColor(R.color.wallpaper_picker_translucent_gray);
             galleryThumbnailBg.setColorFilter(colorOverlay, PorterDuff.Mode.SRC_ATOP);
-
         }
 
         PickImageInfo pickImageInfo = new PickImageInfo();
diff --git a/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java b/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java
deleted file mode 100644
index 8a05051..0000000
--- a/WallpaperPicker/src/com/android/photos/views/BlockingGLTextureView.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.photos.views;
-
-import android.content.Context;
-import android.graphics.SurfaceTexture;
-import android.opengl.GLSurfaceView.Renderer;
-import android.opengl.GLUtils;
-import android.util.Log;
-import android.view.TextureView;
-import android.view.TextureView.SurfaceTextureListener;
-
-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;
-import javax.microedition.khronos.opengles.GL10;
-
-/**
- * A TextureView that supports blocking rendering for synchronous drawing
- */
-public class BlockingGLTextureView extends TextureView
-        implements SurfaceTextureListener {
-
-    private RenderThread mRenderThread;
-
-    public BlockingGLTextureView(Context context) {
-        super(context);
-        setSurfaceTextureListener(this);
-    }
-
-    public void setRenderer(Renderer renderer) {
-        if (mRenderThread != null) {
-            throw new IllegalArgumentException("Renderer already set");
-        }
-        mRenderThread = new RenderThread(renderer);
-    }
-
-    public void render() {
-        mRenderThread.render();
-    }
-
-    public void destroy() {
-        if (mRenderThread != null) {
-            mRenderThread.finish();
-            mRenderThread = null;
-        }
-    }
-
-    @Override
-    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
-            int height) {
-        mRenderThread.setSurface(surface);
-        mRenderThread.setSize(width, height);
-    }
-
-    @Override
-    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
-            int height) {
-        mRenderThread.setSize(width, height);
-    }
-
-    @Override
-    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
-        if (mRenderThread != null) {
-            mRenderThread.setSurface(null);
-        }
-        return false;
-    }
-
-    @Override
-    public void onSurfaceTextureUpdated(SurfaceTexture surface) {
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            destroy();
-        } catch (Throwable t) {
-            // Ignore
-        }
-        super.finalize();
-    }
-
-    /**
-     * An EGL helper class.
-     */
-
-    private static class EglHelper {
-        private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
-        private static final int EGL_OPENGL_ES2_BIT = 4;
-
-        EGL10 mEgl;
-        EGLDisplay mEglDisplay;
-        EGLSurface mEglSurface;
-        EGLConfig mEglConfig;
-        EGLContext mEglContext;
-
-        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 static int[] getConfig() {
-            return new int[] {
-                    EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-                    EGL10.EGL_RED_SIZE, 8,
-                    EGL10.EGL_GREEN_SIZE, 8,
-                    EGL10.EGL_BLUE_SIZE, 8,
-                    EGL10.EGL_ALPHA_SIZE, 8,
-                    EGL10.EGL_DEPTH_SIZE, 0,
-                    EGL10.EGL_STENCIL_SIZE, 0,
-                    EGL10.EGL_NONE
-            };
-        }
-
-        EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
-            int[] attribList = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
-            return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attribList);
-        }
-
-        /**
-         * Initialize EGL for a given configuration spec.
-         */
-        public void start() {
-            /*
-             * Get an EGL instance
-             */
-            mEgl = (EGL10) EGLContext.getEGL();
-
-            /*
-             * Get to the default display.
-             */
-            mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-
-            if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
-                throw new RuntimeException("eglGetDisplay failed");
-            }
-
-            /*
-             * We can now initialize EGL for that display
-             */
-            int[] version = new int[2];
-            if (!mEgl.eglInitialize(mEglDisplay, version)) {
-                throw new RuntimeException("eglInitialize failed");
-            }
-            mEglConfig = chooseEglConfig();
-
-            /*
-            * Create an EGL context. We want to do this as rarely as we can, because an
-            * EGL context is a somewhat heavy object.
-            */
-            mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
-
-            if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {
-                mEglContext = null;
-                throwEglException("createContext");
-            }
-
-            mEglSurface = null;
-        }
-
-        /**
-         * Create an egl surface for the current SurfaceTexture surface. If a surface
-         * already exists, destroy it before creating the new surface.
-         *
-         * @return true if the surface was created successfully.
-         */
-        public boolean createSurface(SurfaceTexture surface) {
-            /*
-             * Check preconditions.
-             */
-            if (mEgl == null) {
-                throw new RuntimeException("egl not initialized");
-            }
-            if (mEglDisplay == null) {
-                throw new RuntimeException("eglDisplay not initialized");
-            }
-            if (mEglConfig == null) {
-                throw new RuntimeException("mEglConfig not initialized");
-            }
-
-            /*
-             *  The window size has changed, so we need to create a new
-             *  surface.
-             */
-            destroySurfaceImp();
-
-            /*
-             * Create an EGL surface we can render into.
-             */
-            if (surface != null) {
-                mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surface, null);
-            } else {
-                mEglSurface = null;
-            }
-
-            if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
-                int error = mEgl.eglGetError();
-                if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
-                    Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
-                }
-                return false;
-            }
-
-            /*
-             * Before we can issue GL commands, we need to make sure
-             * the context is current and bound to a surface.
-             */
-            if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
-                /*
-                 * Could not make the context current, probably because the underlying
-                 * SurfaceView surface has been destroyed.
-                 */
-                logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError());
-                return false;
-            }
-
-            return true;
-        }
-
-        /**
-         * Create a GL object for the current EGL context.
-         */
-        public GL10 createGL() {
-            return (GL10) mEglContext.getGL();
-        }
-
-        /**
-         * Display the current render surface.
-         * @return the EGL error code from eglSwapBuffers.
-         */
-        public int swap() {
-            if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
-                return mEgl.eglGetError();
-            }
-            return EGL10.EGL_SUCCESS;
-        }
-
-        public void destroySurface() {
-            destroySurfaceImp();
-        }
-
-        private void destroySurfaceImp() {
-            if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
-                mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
-                        EGL10.EGL_NO_SURFACE,
-                        EGL10.EGL_NO_CONTEXT);
-                mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
-                mEglSurface = null;
-            }
-        }
-
-        public void finish() {
-            if (mEglContext != null) {
-                mEgl.eglDestroyContext(mEglDisplay, mEglContext);
-                mEglContext = null;
-            }
-            if (mEglDisplay != null) {
-                mEgl.eglTerminate(mEglDisplay);
-                mEglDisplay = null;
-            }
-        }
-
-        private void throwEglException(String function) {
-            throwEglException(function, mEgl.eglGetError());
-        }
-
-        public static void throwEglException(String function, int error) {
-            String message = formatEglError(function, error);
-            throw new RuntimeException(message);
-        }
-
-        public static void logEglErrorAsWarning(String tag, String function, int error) {
-            Log.w(tag, formatEglError(function, error));
-        }
-
-        public static String formatEglError(String function, int error) {
-            return function + " failed: " + error;
-        }
-
-    }
-
-    private static class RenderThread extends Thread {
-        private static final int INVALID = -1;
-        private static final int RENDER = 1;
-        private static final int CHANGE_SURFACE = 2;
-        private static final int RESIZE_SURFACE = 3;
-        private static final int FINISH = 4;
-
-        private EglHelper mEglHelper = new EglHelper();
-
-        private Object mLock = new Object();
-        private int mExecMsgId = INVALID;
-        private SurfaceTexture mSurface;
-        private Renderer mRenderer;
-        private int mWidth, mHeight;
-
-        private boolean mFinished = false;
-        private GL10 mGL;
-
-        public RenderThread(Renderer renderer) {
-            super("RenderThread");
-            mRenderer = renderer;
-            start();
-        }
-
-        private void checkRenderer() {
-            if (mRenderer == null) {
-                throw new IllegalArgumentException("Renderer is null!");
-            }
-        }
-
-        private void checkSurface() {
-            if (mSurface == null) {
-                throw new IllegalArgumentException("surface is null!");
-            }
-        }
-
-        public void setSurface(SurfaceTexture surface) {
-            // If the surface is null we're being torn down, don't need a
-            // renderer then
-            if (surface != null) {
-                checkRenderer();
-            }
-            mSurface = surface;
-            exec(CHANGE_SURFACE);
-        }
-
-        public void setSize(int width, int height) {
-            checkRenderer();
-            checkSurface();
-            mWidth = width;
-            mHeight = height;
-            exec(RESIZE_SURFACE);
-        }
-
-        public void render() {
-            checkRenderer();
-            if (mSurface != null) {
-                exec(RENDER);
-                mSurface.updateTexImage();
-            }
-        }
-
-        public void finish() {
-            mSurface = null;
-            exec(FINISH);
-            try {
-                join();
-            } catch (InterruptedException e) {
-                // Ignore
-            }
-        }
-
-        private void exec(int msgid) {
-            synchronized (mLock) {
-                if (mExecMsgId != INVALID) {
-                    throw new IllegalArgumentException(
-                            "Message already set - multithreaded access?");
-                }
-                mExecMsgId = msgid;
-                mLock.notify();
-                try {
-                    mLock.wait();
-                } catch (InterruptedException e) {
-                    // Ignore
-                }
-            }
-        }
-
-        private void handleMessageLocked(int what) {
-            switch (what) {
-            case CHANGE_SURFACE:
-                if (mEglHelper.createSurface(mSurface)) {
-                    mGL = mEglHelper.createGL();
-                    mRenderer.onSurfaceCreated(mGL, mEglHelper.mEglConfig);
-                }
-                break;
-            case RESIZE_SURFACE:
-                mRenderer.onSurfaceChanged(mGL, mWidth, mHeight);
-                break;
-            case RENDER:
-                mRenderer.onDrawFrame(mGL);
-                mEglHelper.swap();
-                break;
-            case FINISH:
-                mEglHelper.destroySurface();
-                mEglHelper.finish();
-                mFinished = true;
-                break;
-            }
-        }
-
-        @Override
-        public void run() {
-            synchronized (mLock) {
-                mEglHelper.start();
-                while (!mFinished) {
-                    while (mExecMsgId == INVALID) {
-                        try {
-                            mLock.wait();
-                        } catch (InterruptedException e) {
-                            // Ignore
-                        }
-                    }
-                    handleMessageLocked(mExecMsgId);
-                    mExecMsgId = INVALID;
-                    mLock.notify();
-                }
-                mExecMsgId = FINISH;
-            }
-        }
-    }
-}
diff --git a/WallpaperPicker/src/com/android/photos/views/TiledImageView.java b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
index 94063b0..524fa2e 100644
--- a/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
+++ b/WallpaperPicker/src/com/android/photos/views/TiledImageView.java
@@ -16,8 +16,6 @@
 
 package com.android.photos.views;
 
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -28,11 +26,9 @@
 import android.graphics.RectF;
 import android.opengl.GLSurfaceView;
 import android.opengl.GLSurfaceView.Renderer;
-import android.os.Build;
 import android.util.AttributeSet;
 import android.view.Choreographer;
 import android.view.Choreographer.FrameCallback;
-import android.view.View;
 import android.widget.FrameLayout;
 
 import com.android.gallery3d.glrenderer.BasicTexture;
@@ -43,18 +39,10 @@
 import javax.microedition.khronos.opengles.GL10;
 
 /**
- * Shows an image using {@link TiledImageRenderer} using either {@link GLSurfaceView}
- * or {@link BlockingGLTextureView}.
+ * Shows an image using {@link TiledImageRenderer} using either {@link GLSurfaceView}.
  */
 public class TiledImageView extends FrameLayout {
 
-    private static final boolean USE_TEXTURE_VIEW = false;
-    private static final boolean IS_SUPPORTED =
-            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
-    private static final boolean USE_CHOREOGRAPHER =
-            Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
-
-    private BlockingGLTextureView mTextureView;
     private GLSurfaceView mGLSurfaceView;
     private boolean mInvalPending = false;
     private FrameCallback mFrameCallback;
@@ -79,35 +67,19 @@
     protected Object mLock = new Object();
     protected ImageRendererWrapper mRenderer;
 
-    public static boolean isTilingSupported() {
-        return IS_SUPPORTED;
-    }
-
     public TiledImageView(Context context) {
         this(context, null);
     }
 
     public TiledImageView(Context context, AttributeSet attrs) {
         super(context, attrs);
-        if (!IS_SUPPORTED) {
-            return;
-        }
-
         mRenderer = new ImageRendererWrapper();
         mRenderer.image = new TiledImageRenderer(this);
-        View view;
-        if (USE_TEXTURE_VIEW) {
-            mTextureView = new BlockingGLTextureView(context);
-            mTextureView.setRenderer(new TileRenderer());
-            view = mTextureView;
-        } else {
-            mGLSurfaceView = new GLSurfaceView(context);
-            mGLSurfaceView.setEGLContextClientVersion(2);
-            mGLSurfaceView.setRenderer(new TileRenderer());
-            mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
-            view = mGLSurfaceView;
-        }
-        addView(view, new LayoutParams(
+        mGLSurfaceView = new GLSurfaceView(context);
+        mGLSurfaceView.setEGLContextClientVersion(2);
+        mGLSurfaceView.setRenderer(new TileRenderer());
+        mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+        addView(mGLSurfaceView, new LayoutParams(
                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
         //setTileSource(new ColoredTiles());
     }
@@ -117,22 +89,11 @@
         super.setVisibility(visibility);
         // need to update inner view's visibility because it seems like we're causing it to draw
         // from {@link #dispatchDraw} or {@link #invalidate} even if we are invisible.
-        if (USE_TEXTURE_VIEW) {
-            mTextureView.setVisibility(visibility);
-        } else {
-            mGLSurfaceView.setVisibility(visibility);
-        }
+        mGLSurfaceView.setVisibility(visibility);
     }
 
     public void destroy() {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        if (USE_TEXTURE_VIEW) {
-            mTextureView.destroy();
-        } else {
-            mGLSurfaceView.queueEvent(mFreeTextures);
-        }
+        mGLSurfaceView.queueEvent(mFreeTextures);
     }
 
     private Runnable mFreeTextures = new Runnable() {
@@ -144,27 +105,14 @@
     };
 
     public void onPause() {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        if (!USE_TEXTURE_VIEW) {
-            mGLSurfaceView.onPause();
-        }
+        mGLSurfaceView.onPause();
     }
 
     public void onResume() {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        if (!USE_TEXTURE_VIEW) {
-            mGLSurfaceView.onResume();
-        }
+        mGLSurfaceView.onResume();
     }
 
     public void setTileSource(TileSource source, Runnable isReadyCallback) {
-        if (!IS_SUPPORTED) {
-            return;
-        }
         synchronized (mLock) {
             mRenderer.source = source;
             mRenderer.isReadyCallback = isReadyCallback;
@@ -181,9 +129,6 @@
     protected void onLayout(boolean changed, int left, int top, int right,
             int bottom) {
         super.onLayout(changed, left, top, right, bottom);
-        if (!IS_SUPPORTED) {
-            return;
-        }
         synchronized (mLock) {
             updateScaleIfNecessaryLocked(mRenderer);
         }
@@ -200,43 +145,10 @@
     }
 
     @Override
-    protected void dispatchDraw(Canvas canvas) {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        if (USE_TEXTURE_VIEW) {
-            mTextureView.render();
-        }
-        super.dispatchDraw(canvas);
-    }
-
-    @SuppressLint("NewApi")
-    @Override
-    public void setTranslationX(float translationX) {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        super.setTranslationX(translationX);
-    }
-
-    @Override
     public void invalidate() {
-        if (!IS_SUPPORTED) {
-            return;
-        }
-        if (USE_TEXTURE_VIEW) {
-            super.invalidate();
-            mTextureView.invalidate();
-        } else {
-            if (USE_CHOREOGRAPHER) {
-                invalOnVsync();
-            } else {
-                mGLSurfaceView.requestRender();
-            }
-        }
+        invalOnVsync();
     }
 
-    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
     private void invalOnVsync() {
         if (!mInvalPending) {
             mInvalPending = true;
@@ -255,9 +167,6 @@
 
     private RectF mTempRectF = new RectF();
     public void positionFromMatrix(Matrix matrix) {
-        if (!IS_SUPPORTED) {
-            return;
-        }
         if (mRenderer.source != null) {
             final int rotation = mRenderer.source.getRotation();
             final boolean swap = !(rotation % 180 == 0);
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index b08272f..289b08b 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -16,14 +16,12 @@
 
 package com.android.launcher3;
 
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
@@ -33,7 +31,6 @@
 import java.util.ArrayList;
 
 public class Hotseat extends FrameLayout {
-    private static final String TAG = "Hotseat";
 
     private CellLayout mContent;
 
@@ -182,38 +179,6 @@
         return false;
     }
 
-    void addAllAppsFolder(IconCache iconCache,
-            ArrayList<AppInfo> allApps, ArrayList<ComponentName> onWorkspace,
-            Launcher launcher, Workspace workspace) {
-        if (LauncherAppState.isDisableAllApps()) {
-            FolderInfo fi = new FolderInfo();
-
-            fi.cellX = getCellXFromOrder(mAllAppsButtonRank);
-            fi.cellY = getCellYFromOrder(mAllAppsButtonRank);
-            fi.spanX = 1;
-            fi.spanY = 1;
-            fi.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT;
-            fi.screenId = mAllAppsButtonRank;
-            fi.itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
-            fi.title = "More Apps";
-            LauncherModel.addItemToDatabase(launcher, fi, fi.container, fi.screenId, fi.cellX,
-                    fi.cellY, false);
-            FolderIcon folder = FolderIcon.fromXml(R.layout.folder_icon, launcher,
-                    getLayout(), fi, iconCache);
-            workspace.addInScreen(folder, fi.container, fi.screenId, fi.cellX, fi.cellY,
-                    fi.spanX, fi.spanY);
-
-            for (AppInfo info: allApps) {
-                ComponentName cn = info.intent.getComponent();
-                if (!onWorkspace.contains(cn)) {
-                    Log.d(TAG, "Adding to 'more apps': " + info.intent);
-                    ShortcutInfo si = info.makeShortcut();
-                    fi.add(si);
-                }
-            }
-        }
-    }
-
     void addAppsToAllAppsFolder(ArrayList<AppInfo> apps) {
         if (LauncherAppState.isDisableAllApps()) {
             View v = mContent.getChildAt(getCellXFromOrder(mAllAppsButtonRank), getCellYFromOrder(mAllAppsButtonRank));
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 61915b7..7445b8c 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -95,6 +95,7 @@
 import android.widget.Advanceable;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
+import android.widget.TextView;
 import android.widget.Toast;
 
 import com.android.launcher3.DropTarget.DragObject;
@@ -115,6 +116,9 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.text.DateFormat;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -227,8 +231,6 @@
     private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
     private static final int ACTIVITY_START_DELAY = 1000;
 
-    private static final Object sLock = new Object();
-
     private HashMap<Integer, Integer> mItemIdToViewId = new HashMap<Integer, Integer>();
     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
 
@@ -306,6 +308,9 @@
 
     private View.OnTouchListener mHapticFeedbackTouchListener;
 
+    public static final int BUILD_LAYER = 0;
+    public static final int BUILD_AND_SET_LAYER = 1;
+
     // Related to the auto-advancing of widgets
     private final int ADVANCE_MSG = 1;
     private final int mAdvanceInterval = 20000;
@@ -335,8 +340,6 @@
     // it from the context.
     private SharedPreferences mSharedPrefs;
 
-    private static ArrayList<ComponentName> mIntentsOnWorkspaceFromUpgradePath = null;
-
     // Holds the page that we need to animate to, and the icon views that we need to animate up
     // when we scroll to that page on resume.
     private ImageView mFolderIconImageView;
@@ -356,6 +359,18 @@
         }
     }
 
+    // TODO: remove this field and call method directly when Launcher3 can depend on M APIs
+    private static Method sClipRevealMethod = null;
+    static {
+        Class<?> activityOptionsClass = ActivityOptions.class;
+        try {
+            sClipRevealMethod = activityOptionsClass.getDeclaredMethod("makeClipRevealAnimation",
+                    View.class, int.class, int.class, int.class, int.class);
+        } catch (Exception e) {
+            // Earlier version
+        }
+    }
+
     private Runnable mBuildLayersRunnable = new Runnable() {
         public void run() {
             if (mWorkspace != null) {
@@ -2894,9 +2909,41 @@
 
             Bundle optsBundle = null;
             if (useLaunchAnimation) {
-                ActivityOptions opts = Utilities.isLmpOrAbove() ?
-                        ActivityOptions.makeCustomAnimation(this, R.anim.task_open_enter, R.anim.no_anim) :
-                        ActivityOptions.makeScaleUpAnimation(v, 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
+                ActivityOptions opts = null;
+                if (sClipRevealMethod != null) {
+                    // TODO: call method directly when Launcher3 can depend on M APIs
+                    int left = 0, top = 0;
+                    int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
+                    if (v instanceof TextView) {
+                        // Launch from center of icon, not entire view
+                        TextView tv = (TextView) v;
+                        Drawable[] drawables = tv.getCompoundDrawables();
+                        if (drawables != null && drawables[1] != null) {
+                            Rect bounds = drawables[1].getBounds();
+                            left = (width - bounds.width()) / 2;
+                            top = tv.getPaddingTop();
+                            width = bounds.width();
+                            height = bounds.height();
+                        }
+                    }
+                    try {
+                        opts = (ActivityOptions) sClipRevealMethod.invoke(null, v,
+                                left, top, width, height);
+                    } catch (IllegalAccessException e) {
+                        Log.d(TAG, "Could not call makeClipRevealAnimation: " + e);
+                        sClipRevealMethod = null;
+                    } catch (InvocationTargetException e) {
+                        Log.d(TAG, "Could not call makeClipRevealAnimation: " + e);
+                        sClipRevealMethod = null;
+                    }
+                }
+                if (opts == null) {
+                    opts = Utilities.isLmpOrAbove() ?
+                            ActivityOptions.makeCustomAnimation(this,
+                                    R.anim.task_open_enter, R.anim.no_anim) :
+                            ActivityOptions.makeScaleUpAnimation(v, 0, 0,
+                                    v.getMeasuredWidth(), v.getMeasuredHeight());
+                }
                 optsBundle = opts.toBundle();
             }
 
@@ -3291,7 +3338,7 @@
         final View fromView = mWorkspace;
         final AppsCustomizeTabHost toView = mAppsCustomizeTabHost;
 
-        final ArrayList<View> layerViews = new ArrayList<View>();
+        final HashMap<View, Integer> layerViews = new HashMap<View, Integer>();
 
         Workspace.State workspaceState = contentType == AppsCustomizePagedView.ContentType.Widgets ?
                 Workspace.State.OVERVIEW_HIDDEN : Workspace.State.NORMAL_HIDDEN;
@@ -3351,8 +3398,7 @@
             }
             final float initAlpha = alpha;
 
-            revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-            layerViews.add(revealView);
+            layerViews.put(revealView, BUILD_AND_SET_LAYER);
             PropertyValuesHolder panelAlpha = PropertyValuesHolder.ofFloat("alpha", initAlpha, 1f);
             PropertyValuesHolder panelDriftY =
                     PropertyValuesHolder.ofFloat("translationY", yDrift, 0);
@@ -3369,8 +3415,7 @@
 
             if (page != null) {
                 page.setVisibility(View.VISIBLE);
-                page.setLayerType(View.LAYER_TYPE_HARDWARE, null);
-                layerViews.add(page);
+                layerViews.put(page, BUILD_AND_SET_LAYER);
 
                 ObjectAnimator pageDrift = ObjectAnimator.ofFloat(page, "translationY", yDrift, 0);
                 page.setTranslationY(yDrift);
@@ -3426,9 +3471,11 @@
                     dispatchOnLauncherTransitionEnd(toView, animated, false);
 
                     revealView.setVisibility(View.INVISIBLE);
-                    revealView.setLayerType(View.LAYER_TYPE_NONE, null);
-                    if (page != null) {
-                        page.setLayerType(View.LAYER_TYPE_NONE, null);
+
+                    for (View v : layerViews.keySet()) {
+                        if (layerViews.get(v) == BUILD_AND_SET_LAYER) {
+                            v.setLayerType(View.LAYER_TYPE_NONE, null);
+                        }
                     }
                     content.setPageBackgroundsVisible(true);
 
@@ -3460,12 +3507,16 @@
                     dispatchOnLauncherTransitionStart(toView, animated, false);
 
                     revealView.setAlpha(initAlpha);
+
+                    for (View v : layerViews.keySet()) {
+                        if (layerViews.get(v) == BUILD_AND_SET_LAYER) {
+                            v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                        }
+                    }
+
                     if (Utilities.isLmpOrAbove()) {
-                        for (int i = 0; i < layerViews.size(); i++) {
-                            View v = layerViews.get(i);
-                            if (v != null) {
-                                if (Utilities.isViewAttachedToWindow(v)) v.buildLayer();
-                            }
+                        for (View v : layerViews.keySet()) {
+                            if (Utilities.isViewAttachedToWindow(v)) v.buildLayer();
                         }
                     }
                     mStateAnimation.start();
@@ -3521,7 +3572,7 @@
         final View fromView = mAppsCustomizeTabHost;
         final View toView = mWorkspace;
         Animator workspaceAnim = null;
-        final ArrayList<View> layerViews = new ArrayList<View>();
+        final HashMap<View, Integer> layerViews = new HashMap<View, Integer>();
 
         if (toState == Workspace.State.NORMAL) {
             workspaceAnim = mWorkspace.getChangeStateAnimation(
@@ -3593,7 +3644,7 @@
                     xDrift = 0;
                 }
 
-                revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                layerViews.put(revealView, BUILD_AND_SET_LAYER);
                 TimeInterpolator decelerateInterpolator = material ?
                         new LogDecelerateInterpolator(100, 0) :
                         new DecelerateInterpolator(1f);
@@ -3627,7 +3678,7 @@
                 }
 
                 if (page != null) {
-                    page.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                    layerViews.put(page, BUILD_AND_SET_LAYER);
 
                     ObjectAnimator pageDrift = LauncherAnimUtils.ofFloat(page, "translationY",
                             0, yDrift);
@@ -3695,10 +3746,12 @@
                         onCompleteRunnable.run();
                     }
 
-                    revealView.setLayerType(View.LAYER_TYPE_NONE, null);
-                    if (page != null) {
-                        page.setLayerType(View.LAYER_TYPE_NONE, null);
+                    for (View v : layerViews.keySet()) {
+                        if (layerViews.get(v) == BUILD_AND_SET_LAYER) {
+                            v.setLayerType(View.LAYER_TYPE_NONE, null);
+                        }
                     }
+
                     content.setPageBackgroundsVisible(true);
                     // Unhide side pages
                     int count = content.getChildCount();
@@ -3732,12 +3785,15 @@
                     dispatchOnLauncherTransitionStart(fromView, animated, false);
                     dispatchOnLauncherTransitionStart(toView, animated, false);
 
+                    for (View v : layerViews.keySet()) {
+                        if (layerViews.get(v) == BUILD_AND_SET_LAYER) {
+                            v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+                        }
+                    }
+
                     if (Utilities.isLmpOrAbove()) {
-                        for (int i = 0; i < layerViews.size(); i++) {
-                            View v = layerViews.get(i);
-                            if (v != null) {
-                                if (Utilities.isViewAttachedToWindow(v)) v.buildLayer();
-                            }
+                        for (View v : layerViews.keySet()) {
+                            if (Utilities.isViewAttachedToWindow(v)) v.buildLayer();
                         }
                     }
                     mStateAnimation.start();
@@ -3910,8 +3966,11 @@
             }
 
             Bundle opts = new Bundle();
+            // We indicate that this widget is both acting as a search box affordance as well
+            // as being present on the home screen.
             opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
-                    AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
+                    AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX |
+                    AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN);
 
             SharedPreferences sp = getSharedPreferences(
                     LauncherAppState.getSharedPreferencesKey(), MODE_PRIVATE);
@@ -4451,10 +4510,10 @@
      *
      * Implementation of the method from LauncherModel.Callbacks.
      */
-    public void finishBindingItems(final boolean upgradePath) {
+    public void finishBindingItems() {
         Runnable r = new Runnable() {
             public void run() {
-                finishBindingItems(upgradePath);
+                finishBindingItems();
             }
         };
         if (waitUntilResume(r)) {
@@ -4489,14 +4548,10 @@
             sPendingAddItem = null;
         }
 
-        if (upgradePath) {
-            mWorkspace.getUniqueComponents(true, null);
-            mIntentsOnWorkspaceFromUpgradePath = mWorkspace.getUniqueComponents(true, null);
-        }
         PackageInstallerCompat.getInstance(this).onFinishBind();
 
         if (mLauncherCallbacks != null) {
-            mLauncherCallbacks.finishBindingItems(upgradePath);
+            mLauncherCallbacks.finishBindingItems(false);
         }
     }
 
@@ -4563,13 +4618,6 @@
      */
     public void bindAllApplications(final ArrayList<AppInfo> apps) {
         if (LauncherAppState.isDisableAllApps()) {
-            if (mIntentsOnWorkspaceFromUpgradePath != null) {
-                if (LauncherModel.UPGRADE_USE_MORE_APPS_FOLDER) {
-                    getHotseat().addAllAppsFolder(mIconCache, apps,
-                            mIntentsOnWorkspaceFromUpgradePath, Launcher.this, mWorkspace);
-                }
-                mIntentsOnWorkspaceFromUpgradePath = null;
-            }
             if (mAppsCustomizeContent != null) {
                 mAppsCustomizeContent.onPackagesUpdated(
                         LauncherModel.getSortedWidgetsAndShortcuts(this));
@@ -4779,8 +4827,12 @@
 
     public void lockScreenOrientation() {
         if (Utilities.isRotationEnabled(this)) {
-            setRequestedOrientation(mapConfigurationOriActivityInfoOri(getResources()
-                    .getConfiguration().orientation));
+            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
+                setRequestedOrientation(mapConfigurationOriActivityInfoOri(getResources()
+                        .getConfiguration().orientation));
+            } else {
+                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
+            }
         }
     }
     public void unlockScreenOrientation(boolean immediate) {
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index 2d04df2..954d2d7 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -145,9 +145,9 @@
     @Override
     public AppWidgetProviderInfo getAppWidgetInfo() {
         AppWidgetProviderInfo info = super.getAppWidgetInfo();
-        if (!(info instanceof LauncherAppWidgetProviderInfo)) {
+        if (info != null && !(info instanceof LauncherAppWidgetProviderInfo)) {
             throw new IllegalStateException("Launcher widget must have"
-                    + "LauncherAppWidgetProviderInfo");
+                    + " LauncherAppWidgetProviderInfo");
         }
         return info;
     }
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index f3d94db..3983835 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -90,9 +90,6 @@
 
     static final String TAG = "Launcher.Model";
 
-    // true = use a "More Apps" folder for non-workspace apps on upgrade
-    // false = strew non-workspace apps across the workspace on upgrade
-    public static final boolean UPGRADE_USE_MORE_APPS_FOLDER = false;
     public static final int LOADER_FLAG_NONE = 0;
     public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0;
     public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1;
@@ -198,7 +195,7 @@
         public void bindScreens(ArrayList<Long> orderedScreenIds);
         public void bindAddScreens(ArrayList<Long> orderedScreenIds);
         public void bindFolders(HashMap<Long,FolderInfo> folders);
-        public void finishBindingItems(boolean upgradePath);
+        public void finishBindingItems();
         public void bindAppWidget(LauncherAppWidgetInfo info);
         public void bindAllApplications(ArrayList<AppInfo> apps);
         public void bindAppsAdded(ArrayList<Long> newScreens,
@@ -1501,8 +1498,7 @@
             return mIsLoadingAndBindingWorkspace;
         }
 
-        /** Returns whether this is an upgrade path */
-        private boolean loadAndBindWorkspace() {
+        private void loadAndBindWorkspace() {
             mIsLoadingAndBindingWorkspace = true;
 
             // Load the workspace
@@ -1510,20 +1506,18 @@
                 Log.d(TAG, "loadAndBindWorkspace mWorkspaceLoaded=" + mWorkspaceLoaded);
             }
 
-            boolean isUpgradePath = false;
             if (!mWorkspaceLoaded) {
-                isUpgradePath = loadWorkspace();
+                loadWorkspace();
                 synchronized (LoaderTask.this) {
                     if (mStopped) {
-                        return isUpgradePath;
+                        return;
                     }
                     mWorkspaceLoaded = true;
                 }
             }
 
             // Bind the workspace
-            bindWorkspace(-1, isUpgradePath);
-            return isUpgradePath;
+            bindWorkspace(-1);
         }
 
         private void waitForIdle() {
@@ -1592,15 +1586,13 @@
 
             // Divide the set of loaded items into those that we are binding synchronously, and
             // everything else that is to be bound normally (asynchronously).
-            bindWorkspace(synchronousBindPage, false);
+            bindWorkspace(synchronousBindPage);
             // XXX: For now, continue posting the binding of AllApps as there are other issues that
             //      arise from that.
             onlyBindAllApps();
         }
 
         public void run() {
-            boolean isUpgrade = false;
-
             synchronized (mLock) {
                 mIsLoaderTaskRunning = true;
             }
@@ -1617,7 +1609,7 @@
                             ? Process.THREAD_PRIORITY_DEFAULT : Process.THREAD_PRIORITY_BACKGROUND);
                 }
                 if (DEBUG_LOADERS) Log.d(TAG, "step 1: loading workspace");
-                isUpgrade = loadAndBindWorkspace();
+                loadAndBindWorkspace();
 
                 if (mStopped) {
                     break keep_running;
@@ -1655,9 +1647,7 @@
             if (LauncherAppState.isDisableAllApps()) {
                 // Ensure that all the applications that are in the system are
                 // represented on the home screen.
-                if (!UPGRADE_USE_MORE_APPS_FOLDER || !isUpgrade) {
-                    verifyApplications();
-                }
+                verifyApplications();
             }
 
             // Clear out this reference, otherwise we end up holding it until all of the
@@ -1834,8 +1824,7 @@
             }
         }
 
-        /** Returns whether this is an upgrade path */
-        private boolean loadWorkspace() {
+        private void loadWorkspace() {
             // Log to disk
             Launcher.addDumpLog(TAG, "11683562 - loadWorkspace()", true);
 
@@ -1869,12 +1858,6 @@
                 LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary();
             }
 
-            // This code path is for our old migration code and should no longer be exercised
-            boolean loadedOldDb = false;
-
-            // Log to disk
-            Launcher.addDumpLog(TAG, "11683562 -   loadedOldDb: " + loadedOldDb, true);
-
             synchronized (sBgLock) {
                 clearSBgDataStructures();
                 final HashSet<String> installingPkgs = PackageInstallerCompat
@@ -2347,7 +2330,7 @@
                 // Break early if we've stopped loading
                 if (mStopped) {
                     clearSBgDataStructures();
-                    return false;
+                    return;
                 }
 
                 if (itemsToRemove.size() > 0) {
@@ -2393,60 +2376,29 @@
                             null, sWorker);
                 }
 
-                if (loadedOldDb) {
-                    long maxScreenId = 0;
-                    // If we're importing we use the old screen order.
-                    for (ItemInfo item: sBgItemsIdMap.values()) {
-                        long screenId = item.screenId;
-                        if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
-                                !sBgWorkspaceScreens.contains(screenId)) {
-                            sBgWorkspaceScreens.add(screenId);
-                            if (screenId > maxScreenId) {
-                                maxScreenId = screenId;
-                            }
-                        }
-                    }
-                    Collections.sort(sBgWorkspaceScreens);
-                    // Log to disk
-                    Launcher.addDumpLog(TAG, "11683562 -   maxScreenId: " + maxScreenId, true);
-                    Launcher.addDumpLog(TAG, "11683562 -   sBgWorkspaceScreens: " +
-                            TextUtils.join(", ", sBgWorkspaceScreens), true);
+                sBgWorkspaceScreens.addAll(loadWorkspaceScreensDb(mContext));
+                // Log to disk
+                Launcher.addDumpLog(TAG, "11683562 -   sBgWorkspaceScreens: " +
+                        TextUtils.join(", ", sBgWorkspaceScreens), true);
 
-                    LauncherAppState.getLauncherProvider().updateMaxScreenId(maxScreenId);
+                // Remove any empty screens
+                ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens);
+                for (ItemInfo item: sBgItemsIdMap.values()) {
+                    long screenId = item.screenId;
+                    if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
+                            unusedScreens.contains(screenId)) {
+                        unusedScreens.remove(screenId);
+                    }
+                }
+
+                // If there are any empty screens remove them, and update.
+                if (unusedScreens.size() != 0) {
+                    // Log to disk
+                    Launcher.addDumpLog(TAG, "11683562 -   unusedScreens (to be removed): " +
+                            TextUtils.join(", ", unusedScreens), true);
+
+                    sBgWorkspaceScreens.removeAll(unusedScreens);
                     updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
-
-                    // Update the max item id after we load an old db
-                    long maxItemId = 0;
-                    // If we're importing we use the old screen order.
-                    for (ItemInfo item: sBgItemsIdMap.values()) {
-                        maxItemId = Math.max(maxItemId, item.id);
-                    }
-                    LauncherAppState.getLauncherProvider().updateMaxItemId(maxItemId);
-                } else {
-                    sBgWorkspaceScreens.addAll(loadWorkspaceScreensDb(mContext));
-                    // Log to disk
-                    Launcher.addDumpLog(TAG, "11683562 -   sBgWorkspaceScreens: " +
-                            TextUtils.join(", ", sBgWorkspaceScreens), true);
-
-                    // Remove any empty screens
-                    ArrayList<Long> unusedScreens = new ArrayList<Long>(sBgWorkspaceScreens);
-                    for (ItemInfo item: sBgItemsIdMap.values()) {
-                        long screenId = item.screenId;
-                        if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP &&
-                                unusedScreens.contains(screenId)) {
-                            unusedScreens.remove(screenId);
-                        }
-                    }
-
-                    // If there are any empty screens remove them, and update.
-                    if (unusedScreens.size() != 0) {
-                        // Log to disk
-                        Launcher.addDumpLog(TAG, "11683562 -   unusedScreens (to be removed): " +
-                                TextUtils.join(", ", unusedScreens), true);
-
-                        sBgWorkspaceScreens.removeAll(unusedScreens);
-                        updateWorkspaceScreenOrder(context, sBgWorkspaceScreens);
-                    }
                 }
 
                 if (DEBUG_LOADERS) {
@@ -2475,7 +2427,6 @@
                     }
                 }
             }
-            return loadedOldDb;
         }
 
         /**
@@ -2683,7 +2634,7 @@
         /**
          * Binds all loaded data to actual views on the main thread.
          */
-        private void bindWorkspace(int synchronizeBindPage, final boolean isUpgradePath) {
+        private void bindWorkspace(int synchronizeBindPage) {
             final long t = SystemClock.uptimeMillis();
             Runnable r;
 
@@ -2787,7 +2738,7 @@
                 public void run() {
                     Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                     if (callbacks != null) {
-                        callbacks.finishBindingItems(isUpgradePath);
+                        callbacks.finishBindingItems();
                     }
 
                     // If we're profiling, ensure this is the last thing in the queue.
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 196f57c..ab1347b 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -65,7 +65,6 @@
     static final String TABLE_FAVORITES = "favorites";
     static final String TABLE_WORKSPACE_SCREENS = "workspaceScreens";
     static final String PARAMETER_NOTIFY = "notify";
-    static final String UPGRADED_FROM_OLD_DATABASE = "UPGRADED_FROM_OLD_DATABASE";
     static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
 
     private static final String URI_PARAM_IS_EXTERNAL_ADD = "isExternalAdd";
@@ -250,12 +249,6 @@
         return mOpenHelper.generateNewScreenId();
     }
 
-    // This is only required one time while loading the workspace during the
-    // upgrade path, and should never be called from anywhere else.
-    public void updateMaxScreenId(long maxScreenId) {
-        mOpenHelper.updateMaxScreenId(maxScreenId);
-    }
-
     /**
      * Clears all the data for a fresh start.
      */
@@ -473,19 +466,13 @@
         private void setFlagJustLoadedOldDb() {
             String spKey = LauncherAppState.getSharedPreferencesKey();
             SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
-            SharedPreferences.Editor editor = sp.edit();
-            editor.putBoolean(UPGRADED_FROM_OLD_DATABASE, true);
-            editor.putBoolean(EMPTY_DATABASE_CREATED, false);
-            editor.commit();
+            sp.edit().putBoolean(EMPTY_DATABASE_CREATED, false).commit();
         }
 
         private void setFlagEmptyDbCreated() {
             String spKey = LauncherAppState.getSharedPreferencesKey();
             SharedPreferences sp = mContext.getSharedPreferences(spKey, Context.MODE_PRIVATE);
-            SharedPreferences.Editor editor = sp.edit();
-            editor.putBoolean(EMPTY_DATABASE_CREATED, true);
-            editor.putBoolean(UPGRADED_FROM_OLD_DATABASE, false);
-            editor.commit();
+            sp.edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit();
         }
 
         @Override
@@ -620,7 +607,8 @@
                         new String[] {Integer.toString(LauncherSettings.Favorites.ITEM_TYPE_FOLDER)});
 
                 while (c.moveToNext()) {
-                    db.execSQL("UPDATE favorites SET rank=cellX+(cellY*?) WHERE container=?;",
+                    db.execSQL("UPDATE favorites SET rank=cellX+(cellY*?) WHERE "
+                            + "container=? AND cellX IS NOT NULL AND cellY IS NOT NULL;",
                             new Object[] {c.getLong(1) + 1, c.getLong(0)});
                 }
 
@@ -726,12 +714,6 @@
             return mMaxScreenId;
         }
 
-        public void updateMaxScreenId(long maxScreenId) {
-            // Log to disk
-            Launcher.addDumpLog(TAG, "11683562 - updateMaxScreenId(): " + maxScreenId, true);
-            mMaxScreenId = maxScreenId;
-        }
-
         private long initializeMaxScreenId(SQLiteDatabase db) {
             Cursor c = db.rawQuery("SELECT MAX(" + LauncherSettings.WorkspaceScreens._ID + ") FROM " + TABLE_WORKSPACE_SCREENS, null);
 
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 66e370b..1a4afe8 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -43,7 +43,6 @@
 import android.graphics.Rect;
 import android.graphics.Region.Op;
 import android.graphics.drawable.Drawable;
-import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.IBinder;
@@ -560,10 +559,6 @@
     }
 
     public long insertNewWorkspaceScreen(long screenId, int insertIndex) {
-        // Log to disk
-        Launcher.addDumpLog(TAG, "11683562 - insertNewWorkspaceScreen(): " + screenId +
-                " at index: " + insertIndex, true);
-
         if (mWorkspaceScreens.containsKey(screenId)) {
             throw new RuntimeException("Screen id " + screenId + " already exists!");
         }
@@ -663,9 +658,6 @@
     }
 
     public void addExtraEmptyScreenOnDrag() {
-        // Log to disk
-        Launcher.addDumpLog(TAG, "11683562 - addExtraEmptyScreenOnDrag()", true);
-
         boolean lastChildOnScreen = false;
         boolean childOnFinalScreen = false;
 
@@ -692,9 +684,6 @@
     }
 
     public boolean addExtraEmptyScreen() {
-        // Log to disk
-        Launcher.addDumpLog(TAG, "11683562 - addExtraEmptyScreen()", true);
-
         if (!mWorkspaceScreens.containsKey(EXTRA_EMPTY_SCREEN_ID)) {
             insertNewWorkspaceScreen(EXTRA_EMPTY_SCREEN_ID);
             return true;
@@ -703,9 +692,6 @@
     }
 
     private void convertFinalScreenToEmptyScreenIfNecessary() {
-        // Log to disk
-        Launcher.addDumpLog(TAG, "11683562 - convertFinalScreenToEmptyScreenIfNecessary()", true);
-
         if (mLauncher.isWorkspaceLoading()) {
             // Invalid and dangerous operation if workspace is loading
             Launcher.addDumpLog(TAG, "    - workspace loading, skip", true);
@@ -730,7 +716,6 @@
 
             // Update the model if we have changed any screens
             mLauncher.getModel().updateWorkspaceScreenOrder(mLauncher, mScreenOrder);
-            Launcher.addDumpLog(TAG, "11683562 -   extra empty screen: " + finalScreenId, true);
         }
     }
 
@@ -740,8 +725,6 @@
 
     public void removeExtraEmptyScreenDelayed(final boolean animate, final Runnable onComplete,
             final int delay, final boolean stripEmptyScreens) {
-        // Log to disk
-        Launcher.addDumpLog(TAG, "11683562 - removeExtraEmptyScreen()", true);
         if (mLauncher.isWorkspaceLoading()) {
             // Don't strip empty screens if the workspace is still loading
             Launcher.addDumpLog(TAG, "    - workspace loading, skip", true);
@@ -783,9 +766,7 @@
 
     private void fadeAndRemoveEmptyScreen(int delay, int duration, final Runnable onComplete,
             final boolean stripEmptyScreens) {
-        // Log to disk
         // XXX: Do we need to update LM workspace screens below?
-        Launcher.addDumpLog(TAG, "11683562 - fadeAndRemoveEmptyScreen()", true);
         PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0f);
         PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat("backgroundAlpha", 0f);
 
@@ -829,8 +810,6 @@
     }
 
     public long commitExtraEmptyScreen() {
-        // Log to disk
-        Launcher.addDumpLog(TAG, "11683562 - commitExtraEmptyScreen()", true);
         if (mLauncher.isWorkspaceLoading()) {
             // Invalid and dangerous operation if workspace is loading
             Launcher.addDumpLog(TAG, "    - workspace loading, skip", true);
@@ -889,9 +868,6 @@
     }
 
     public void stripEmptyScreens() {
-        // Log to disk
-        Launcher.addDumpLog(TAG, "11683562 - stripEmptyScreens()", true);
-
         if (mLauncher.isWorkspaceLoading()) {
             // Don't strip empty screens if the workspace is still loading.
             // This is dangerous and can result in data loss.
@@ -919,7 +895,6 @@
 
         int pageShift = 0;
         for (Long id: removeScreens) {
-            Launcher.addDumpLog(TAG, "11683562 -   removing id: " + id, true);
             CellLayout cl = mWorkspaceScreens.get(id);
             mWorkspaceScreens.remove(id);
             mScreenOrder.remove(id);
@@ -2090,7 +2065,7 @@
     }
 
     Animator getChangeStateAnimation(final State state, boolean animated,
-            ArrayList<View> layerViews) {
+            HashMap<View, Integer> layerViews) {
         return getChangeStateAnimation(state, animated, 0, -1, layerViews);
     }
 
@@ -2221,7 +2196,7 @@
     }
 
     Animator getChangeStateAnimation(final State state, boolean animated, int delay, int snapPage,
-            ArrayList<View> layerViews) {
+            HashMap<View, Integer> layerViews) {
         if (mState == state) {
             return null;
         }
@@ -2351,7 +2326,7 @@
                     cl.setShortcutAndWidgetAlpha(mNewAlphas[i]);
                 } else {
                     if (layerViews != null) {
-                        layerViews.add(cl);
+                        layerViews.put(cl, Launcher.BUILD_LAYER);
                     }
                     if (mOldAlphas[i] != mNewAlphas[i] || currentAlpha != mNewAlphas[i]) {
                         LauncherViewPropertyAnimator alphaAnim =
@@ -2388,12 +2363,12 @@
                 pageIndicatorAlpha = ValueAnimator.ofFloat(0, 0);
             }
 
-            Animator hotseatAlpha = new LauncherViewPropertyAnimator(hotseat)
-                .alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
+            LauncherViewPropertyAnimator hotseatAlpha = new LauncherViewPropertyAnimator(hotseat)
+                .alpha(finalHotseatAndPageIndicatorAlpha);
             hotseatAlpha.addListener(new AlphaUpdateListener(hotseat));
 
-            Animator overviewPanelAlpha = new LauncherViewPropertyAnimator(overviewPanel)
-                .alpha(finalOverviewPanelAlpha).withLayer();
+            LauncherViewPropertyAnimator overviewPanelAlpha =
+                    new LauncherViewPropertyAnimator(overviewPanel).alpha(finalOverviewPanelAlpha);
             overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
 
             // For animation optimations, we may need to provide the Launcher transition
@@ -2401,8 +2376,14 @@
             hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null);
             overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
             if (layerViews != null) {
-                layerViews.add(hotseat);
-                layerViews.add(overviewPanel);
+                // If layerViews is not null, we add these views, and indicate that
+                // the caller can manage layer state.
+                layerViews.put(hotseat, Launcher.BUILD_AND_SET_LAYER);
+                layerViews.put(overviewPanel, Launcher.BUILD_AND_SET_LAYER);
+            } else {
+                // Otherwise let the animator handle layer management.
+                hotseatAlpha.withLayer();
+                overviewPanelAlpha.withLayer();
             }
 
             if (workspaceToOverview) {
@@ -2420,12 +2401,17 @@
             hotseatAlpha.setDuration(duration);
 
             if (searchBar != null) {
-                Animator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
-                    .alpha(finalSearchBarAlpha).withLayer();
+                LauncherViewPropertyAnimator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
+                    .alpha(finalSearchBarAlpha);
                 searchBarAlpha.addListener(new AlphaUpdateListener(searchBar));
                 searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
                 if (layerViews != null) {
-                    layerViews.add(searchBar);
+                    // If layerViews is not null, we add these views, and indicate that
+                    // the caller can manage layer state.
+                    layerViews.put(searchBar, Launcher.BUILD_AND_SET_LAYER);
+                } else {
+                    // Otherwise let the animator handle layer management.
+                    searchBarAlpha.withLayer();
                 }
                 searchBarAlpha.setDuration(duration);
                 anim.play(searchBarAlpha);
@@ -3165,9 +3151,8 @@
                         // in its final location
 
                         final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
-                        LauncherAppWidgetProviderInfo pInfo = (LauncherAppWidgetProviderInfo)
-                                hostView.getAppWidgetInfo();
-                        if (pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
+                        AppWidgetProviderInfo pInfo = hostView.getAppWidgetInfo();
+                        if (pInfo != null && pInfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
                             final Runnable addResizeFrame = new Runnable() {
                                 public void run() {
                                     DragLayer dragLayer = mLauncher.getDragLayer();
@@ -4104,7 +4089,6 @@
 
         // In the case where we've prebound the widget, we remove it from the DragLayer
         if (finalView instanceof AppWidgetHostView && external) {
-            Log.d(TAG, "6557954 Animate widget drop, final view is appWidgetHostView");
             mLauncher.getDragLayer().removeView(finalView);
         }
 
@@ -4295,88 +4279,6 @@
         }
     }
 
-    ArrayList<ComponentName> getUniqueComponents(boolean stripDuplicates, ArrayList<ComponentName> duplicates) {
-        ArrayList<ComponentName> uniqueIntents = new ArrayList<ComponentName>();
-        getUniqueIntents((CellLayout) mLauncher.getHotseat().getLayout(), uniqueIntents, duplicates, false);
-        int count = getChildCount();
-        for (int i = 0; i < count; i++) {
-            CellLayout cl = (CellLayout) getChildAt(i);
-            getUniqueIntents(cl, uniqueIntents, duplicates, false);
-        }
-        return uniqueIntents;
-    }
-
-    void getUniqueIntents(CellLayout cl, ArrayList<ComponentName> uniqueIntents,
-            ArrayList<ComponentName> duplicates, boolean stripDuplicates) {
-        int count = cl.getShortcutsAndWidgets().getChildCount();
-
-        ArrayList<View> children = new ArrayList<View>();
-        for (int i = 0; i < count; i++) {
-            View v = cl.getShortcutsAndWidgets().getChildAt(i);
-            children.add(v);
-        }
-
-        for (int i = 0; i < count; i++) {
-            View v = children.get(i);
-            ItemInfo info = (ItemInfo) v.getTag();
-            // Null check required as the AllApps button doesn't have an item info
-            if (info instanceof ShortcutInfo) {
-                ShortcutInfo si = (ShortcutInfo) info;
-                ComponentName cn = si.intent.getComponent();
-
-                Uri dataUri = si.intent.getData();
-                // If dataUri is not null / empty or if this component isn't one that would
-                // have previously showed up in the AllApps list, then this is a widget-type
-                // shortcut, so ignore it.
-                if (dataUri != null && !dataUri.equals(Uri.EMPTY)) {
-                    continue;
-                }
-
-                if (!uniqueIntents.contains(cn)) {
-                    uniqueIntents.add(cn);
-                } else {
-                    if (stripDuplicates) {
-                        cl.removeViewInLayout(v);
-                        LauncherModel.deleteItemFromDatabase(mLauncher, si);
-                    }
-                    if (duplicates != null) {
-                        duplicates.add(cn);
-                    }
-                }
-            }
-            if (v instanceof FolderIcon) {
-                FolderIcon fi = (FolderIcon) v;
-                ArrayList<View> items = fi.getFolder().getItemsInReadingOrder();
-                for (int j = 0; j < items.size(); j++) {
-                    if (items.get(j).getTag() instanceof ShortcutInfo) {
-                        ShortcutInfo si = (ShortcutInfo) items.get(j).getTag();
-                        ComponentName cn = si.intent.getComponent();
-
-                        Uri dataUri = si.intent.getData();
-                        // If dataUri is not null / empty or if this component isn't one that would
-                        // have previously showed up in the AllApps list, then this is a widget-type
-                        // shortcut, so ignore it.
-                        if (dataUri != null && !dataUri.equals(Uri.EMPTY)) {
-                            continue;
-                        }
-
-                        if (!uniqueIntents.contains(cn)) {
-                            uniqueIntents.add(cn);
-                        }  else {
-                            if (stripDuplicates) {
-                                fi.getFolderInfo().remove(si);
-                                LauncherModel.deleteItemFromDatabase(mLauncher, si);
-                            }
-                            if (duplicates != null) {
-                                duplicates.add(cn);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
     void saveWorkspaceToDb() {
         saveWorkspaceScreenToDb((CellLayout) mLauncher.getHotseat().getLayout());
         int count = getChildCount();
diff --git a/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java b/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java
index 1d41a6f..ea51aac 100644
--- a/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java
+++ b/src/com/android/launcher3/compat/LauncherActivityInfoCompatV16.java
@@ -29,13 +29,15 @@
 
 
 public class LauncherActivityInfoCompatV16 extends LauncherActivityInfoCompat {
-    private ActivityInfo mActivityInfo;
-    private ComponentName mComponentName;
-    private PackageManager mPm;
+    private final ResolveInfo mResolveInfo;
+    private final ActivityInfo mActivityInfo;
+    private final ComponentName mComponentName;
+    private final PackageManager mPm;
 
     LauncherActivityInfoCompatV16(Context context, ResolveInfo info) {
         super();
-        this.mActivityInfo = info.activityInfo;
+        mResolveInfo = info;
+        mActivityInfo = info.activityInfo;
         mComponentName = new ComponentName(mActivityInfo.packageName, mActivityInfo.name);
         mPm = context.getPackageManager();
     }
@@ -49,31 +51,30 @@
     }
 
     public CharSequence getLabel() {
-        return mActivityInfo.loadLabel(mPm);
+        return mResolveInfo.loadLabel(mPm);
     }
 
     public Drawable getIcon(int density) {
-        Drawable d = null;
-        if (mActivityInfo.getIconResource() != 0) {
-            Resources resources;
+        int iconRes = mResolveInfo.getIconResource();
+        Resources resources = null;
+        Drawable icon = null;
+        // Get the preferred density icon from the app's resources
+        if (density != 0 && iconRes != 0) {
             try {
-                resources = mPm.getResourcesForApplication(mActivityInfo.packageName);
-            } catch (PackageManager.NameNotFoundException e) {
-                resources = null;
-            }
-            if (resources != null) {
-                try {
-                    d = resources.getDrawableForDensity(mActivityInfo.getIconResource(), density);
-                } catch (Resources.NotFoundException e) {
-                    // Return default icon below.
-                }
+                resources = mPm.getResourcesForApplication(mActivityInfo.applicationInfo);
+                icon = resources.getDrawableForDensity(iconRes, density);
+            } catch (NameNotFoundException | Resources.NotFoundException exc) {
             }
         }
-        if (d == null) {
-            Resources resources = Resources.getSystem();
-            d = resources.getDrawableForDensity(android.R.mipmap.sym_def_app_icon, density);
+        // Get the default density icon
+        if (icon == null) {
+            icon = mResolveInfo.loadIcon(mPm);
         }
-        return d;
+        if (icon == null) {
+            resources = Resources.getSystem();
+            icon = resources.getDrawableForDensity(android.R.mipmap.sym_def_app_icon, density);
+        }
+        return icon;
     }
 
     public ApplicationInfo getApplicationInfo() {