am 76ac344c: Merge "Allow the old launcher content URI to be overrided" into ub-now-mister-ugly

* commit '76ac344cb61a74267c04249c9e9feec41a82c504':
  Allow the old launcher content URI to be overrided
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 5ddafea..ad01019 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -30,7 +30,7 @@
     private static final String TAG = "LauncherAppState";
     private static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
 
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;  // STOPSHIP(cwren) temporary for debugging
 
     private final AppFilter mAppFilter;
     private final BuildInfo mBuildInfo;
diff --git a/src/com/android/launcher3/LauncherBackupAgentHelper.java b/src/com/android/launcher3/LauncherBackupAgentHelper.java
index de6aedd..7dd8cde 100644
--- a/src/com/android/launcher3/LauncherBackupAgentHelper.java
+++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java
@@ -61,7 +61,7 @@
     @Override
     public void onCreate() {
         boolean restoreEnabled = 0 != Settings.Secure.getInt(
-                getContentResolver(), SETTING_RESTORE_ENABLED, 0);
+                getContentResolver(), SETTING_RESTORE_ENABLED, 1);
         if (VERBOSE) Log.v(TAG, "restore is " + (restoreEnabled ? "enabled" : "disabled"));
 
         addHelper(LauncherBackupHelper.LAUNCHER_PREFS_PREFIX,
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index d8645aa..bedd440 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -69,12 +69,13 @@
  */
 public class LauncherModel extends BroadcastReceiver {
     static final boolean DEBUG_LOADERS = false;
+    private static final boolean DEBUG_RECEIVER = true;  // STOPSHIP(cwren) temporary for debugging
+
     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;
@@ -1161,7 +1162,7 @@
      */
     @Override
     public void onReceive(Context context, Intent intent) {
-        if (DEBUG_LOADERS) Log.d(TAG, "onReceive intent=" + intent);
+        if (DEBUG_RECEIVER) Log.d(TAG, "onReceive intent=" + intent);
 
         final String action = intent.getAction();
 
diff --git a/src/com/android/launcher3/MainThreadExecutor.java b/src/com/android/launcher3/MainThreadExecutor.java
new file mode 100644
index 0000000..866b17c
--- /dev/null
+++ b/src/com/android/launcher3/MainThreadExecutor.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.launcher3;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import java.util.List;
+import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An executor service that executes its tasks on the main thread.
+ *
+ * Shutting down this executor is not supported.
+ */
+public class MainThreadExecutor extends AbstractExecutorService {
+
+    private Handler mHandler = new Handler(Looper.getMainLooper());
+
+    @Override
+    public void execute(Runnable runnable) {
+        if (Looper.getMainLooper() == Looper.myLooper()) {
+            runnable.run();
+        } else {
+            mHandler.post(runnable);
+        }
+    }
+
+    /**
+     * Not supported and throws an exception when used.
+     */
+    @Override
+    @Deprecated
+    public void shutdown() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not supported and throws an exception when used.
+     */
+    @Override
+    @Deprecated
+    public List<Runnable> shutdownNow() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isShutdown() {
+        return false;
+    }
+
+    @Override
+    public boolean isTerminated() {
+        return false;
+    }
+
+    /**
+     * Not supported and throws an exception when used.
+     */
+    @Override
+    @Deprecated
+    public boolean awaitTermination(long l, TimeUnit timeUnit) throws InterruptedException {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 36152f8..5dad2a8 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -35,6 +35,8 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
 
 abstract class SoftReferenceThreadLocal<T> {
     private ThreadLocal<SoftReference<T>> mThreadLocal;
@@ -137,6 +139,8 @@
     private final ArrayList<SoftReference<Bitmap>> mUnusedBitmaps;
     private final static HashSet<String> sInvalidPackages;
 
+    private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
+
     static {
         sInvalidPackages = new HashSet<String>();
     }
@@ -492,7 +496,8 @@
 
         Drawable drawable = null;
         if (previewImage != 0) {
-            drawable = mPackageManager.getDrawable(packageName, previewImage, null);
+            drawable = mutateOnMainThread(
+                    mPackageManager.getDrawable(packageName, previewImage, null));
             if (drawable == null) {
                 Log.w(TAG, "Can't load widget preview drawable 0x" +
                         Integer.toHexString(previewImage) + " for provider: " + provider);
@@ -511,6 +516,7 @@
             if (cellHSpan < 1) cellHSpan = 1;
             if (cellVSpan < 1) cellVSpan = 1;
 
+            // This Drawable is not directly drawn, so there's no need to mutate it.
             BitmapDrawable previewDrawable = (BitmapDrawable) mContext.getResources()
                     .getDrawable(R.drawable.widget_tile);
             final int previewDrawableWidth = previewDrawable
@@ -548,7 +554,7 @@
                 int yoffset =
                         (int) ((previewDrawableHeight - mAppIconSize * iconScale) / 2);
                 if (iconId > 0)
-                    icon = mIconCache.getFullResIcon(packageName, iconId);
+                    icon = mutateOnMainThread(mIconCache.getFullResIcon(packageName, iconId));
                 if (icon != null) {
                     renderDrawableToBitmap(icon, defaultPreview, hoffset,
                             yoffset, (int) (mAppIconSize * iconScale),
@@ -617,7 +623,7 @@
             c.setBitmap(null);
         }
         // Render the icon
-        Drawable icon = mIconCache.getFullResIcon(info);
+        Drawable icon = mutateOnMainThread(mIconCache.getFullResIcon(info));
 
         int paddingTop = mContext.
                 getResources().getDimensionPixelOffset(R.dimen.shortcut_preview_padding_top);
@@ -677,4 +683,19 @@
         }
     }
 
+    private Drawable mutateOnMainThread(final Drawable drawable) {
+        try {
+            return mMainThreadExecutor.submit(new Callable<Drawable>() {
+                @Override
+                public Drawable call() throws Exception {
+                    return drawable.mutate();
+                }
+            }).get();
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            throw new RuntimeException(e);
+        } catch (ExecutionException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }