Merge changes from topic "demoModeTopic" into ub-launcher3-master

* changes:
  [automerger] Demo mode default layout support am: 2782449da6 am: ea1212a38a
  [automerger] Demo mode default layout support am: 2782449da6
  Demo mode default layout support
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index 3da1996..7d2f753 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -19,6 +19,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.LauncherActivityInfo;
 import android.os.UserHandle;
 
@@ -31,6 +32,10 @@
  */
 public class AppInfo extends ItemInfoWithIcon {
 
+    public static final int FLAG_SYSTEM_UNKNOWN = 0;
+    public static final int FLAG_SYSTEM_YES = 1 << 0;
+    public static final int FLAG_SYSTEM_NO = 1 << 1;
+
     /**
      * The intent used to start the application.
      */
@@ -43,6 +48,11 @@
      */
     public int isDisabled = ShortcutInfo.DEFAULT;
 
+    /**
+     * Stores if the app is a system app or not.
+     */
+    public int isSystemApp;
+
     public AppInfo() {
         itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
     }
@@ -71,6 +81,10 @@
         }
 
         intent = makeLaunchIntent(info);
+
+        isSystemApp = (info.getApplicationInfo().flags & ApplicationInfo.FLAG_SYSTEM) == 0
+                ? FLAG_SYSTEM_NO : FLAG_SYSTEM_YES;
+
     }
 
     public AppInfo(AppInfo info) {
@@ -79,6 +93,7 @@
         title = Utilities.trim(info.title);
         intent = new Intent(info.intent);
         isDisabled = info.isDisabled;
+        isSystemApp = info.isSystemApp;
     }
 
     @Override
diff --git a/src/com/android/launcher3/UninstallDropTarget.java b/src/com/android/launcher3/UninstallDropTarget.java
index 84d6a9b..902fd34 100644
--- a/src/com/android/launcher3/UninstallDropTarget.java
+++ b/src/com/android/launcher3/UninstallDropTarget.java
@@ -21,6 +21,7 @@
 public class UninstallDropTarget extends ButtonDropTarget {
 
     private static final String TAG = "UninstallDropTarget";
+    private static Boolean sUninstallDisabled;
 
     public UninstallDropTarget(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -48,13 +49,22 @@
     }
 
     public static boolean supportsDrop(Context context, ItemInfo info) {
-        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
-        Bundle restrictions = userManager.getUserRestrictions();
-        if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false)
-                || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false)) {
+        if (sUninstallDisabled == null) {
+            UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+            Bundle restrictions = userManager.getUserRestrictions();
+            sUninstallDisabled = restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false)
+                    || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false);
+        }
+        if (sUninstallDisabled) {
             return false;
         }
 
+        if (info instanceof AppInfo) {
+            AppInfo appInfo = (AppInfo) info;
+            if (appInfo.isSystemApp != AppInfo.FLAG_SYSTEM_UNKNOWN) {
+                return (appInfo.isSystemApp & AppInfo.FLAG_SYSTEM_NO) != 0;
+            }
+        }
         return getUninstallTarget(context, info) != null;
     }
 
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index b6876f6..7167778 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -309,6 +309,9 @@
         float highScore = -1;
         int bestHue = -1;
 
+        int[] pixels = new int[samples];
+        int pixelCount = 0;
+
         for (int y = 0; y < height; y += sampleStride) {
             for (int x = 0; x < width; x += sampleStride) {
                 int argb = bitmap.getPixel(x, y);
@@ -326,6 +329,9 @@
                     // Defensively avoid array bounds violations.
                     continue;
                 }
+                if (pixelCount < samples) {
+                    pixels[pixelCount++] = rgb;
+                }
                 float score = hsv[1] * hsv[2];
                 hueScoreHistogram[hue] += score;
                 if (hueScoreHistogram[hue] > highScore) {
@@ -335,31 +341,29 @@
             }
         }
 
-        SparseArray<Float> rgbScores = new SparseArray<Float>();
+        SparseArray<Float> rgbScores = new SparseArray<>();
         int bestColor = 0xff000000;
         highScore = -1;
         // Go back over the RGB colors that match the winning hue,
         // creating a histogram of weighted s*v scores, for up to 100*100 [s,v] buckets.
         // The highest-scoring RGB color wins.
-        for (int y = 0; y < height; y += sampleStride) {
-            for (int x = 0; x < width; x += sampleStride) {
-                int rgb = bitmap.getPixel(x, y) | 0xff000000;
-                Color.colorToHSV(rgb, hsv);
-                int hue = (int) hsv[0];
-                if (hue == bestHue) {
-                    float s = hsv[1];
-                    float v = hsv[2];
-                    int bucket = (int) (s * 100) + (int) (v * 10000);
-                    // Score by cumulative saturation * value.
-                    float score = s * v;
-                    Float oldTotal = rgbScores.get(bucket);
-                    float newTotal = oldTotal == null ? score : oldTotal + score;
-                    rgbScores.put(bucket, newTotal);
-                    if (newTotal > highScore) {
-                        highScore = newTotal;
-                        // All the colors in the winning bucket are very similar. Last in wins.
-                        bestColor = rgb;
-                    }
+        for (int i = 0; i < pixelCount; i++) {
+            int rgb = pixels[i];
+            Color.colorToHSV(rgb, hsv);
+            int hue = (int) hsv[0];
+            if (hue == bestHue) {
+                float s = hsv[1];
+                float v = hsv[2];
+                int bucket = (int) (s * 100) + (int) (v * 10000);
+                // Score by cumulative saturation * value.
+                float score = s * v;
+                Float oldTotal = rgbScores.get(bucket);
+                float newTotal = oldTotal == null ? score : oldTotal + score;
+                rgbScores.put(bucket, newTotal);
+                if (newTotal > highScore) {
+                    highScore = newTotal;
+                    // All the colors in the winning bucket are very similar. Last in wins.
+                    bestColor = rgb;
                 }
             }
         }