Merge "Solve stutter when swiping All Apps the first time" into jb-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c72d106..47278bb 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -24,6 +24,10 @@
     <original-package android:name="com.android.launcher2" />
 
     <permission
+        android:name="com.android.launcher.permission.PRELOAD_WORKSPACE"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="system|signature" />
+    <permission
         android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
         android:protectionLevel="normal"
@@ -103,6 +107,15 @@
             </intent-filter>
         </activity>
 
+        <!-- Intent received used to prepopulate the default workspace. -->
+        <receiver
+            android:name="com.android.launcher2.PreloadReceiver"
+            android:permission="com.android.launcher.permission.PRELOAD_WORKSPACE">
+            <intent-filter>
+                <action android:name="com.android.launcher.action.PRELOAD_WORKSPACE" />
+            </intent-filter>
+        </receiver>
+
         <!-- Intent received used to install shortcuts from other applications -->
         <receiver
             android:name="com.android.launcher2.InstallShortcutReceiver"
diff --git a/res/layout-land/drop_target_bar.xml b/res/layout-land/drop_target_bar.xml
new file mode 100644
index 0000000..55d9421
--- /dev/null
+++ b/res/layout-land/drop_target_bar.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <FrameLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        style="@style/DropTargetButtonContainer"
+        android:layout_weight="1">
+        <!-- Delete target -->
+        <com.android.launcher2.DeleteDropTarget
+            style="@style/DropTargetButton"
+            android:id="@+id/delete_target_text"
+            android:drawableTop="@drawable/info_target_selector" />
+    </FrameLayout>
+    <FrameLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        style="@style/DropTargetButtonContainer"
+        android:layout_weight="1">
+        <!-- Info target -->
+        <com.android.launcher2.InfoDropTarget
+            style="@style/DropTargetButton"
+            android:id="@+id/info_target_text"
+            android:drawableTop="@drawable/info_target_selector" />
+    </FrameLayout>
+</merge>
\ No newline at end of file
diff --git a/res/layout-port/drop_target_bar.xml b/res/layout-port/drop_target_bar.xml
new file mode 100644
index 0000000..5fcddc9
--- /dev/null
+++ b/res/layout-port/drop_target_bar.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 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.
+-->
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+    <FrameLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        style="@style/DropTargetButtonContainer"
+        android:layout_weight="1">
+        <!-- Delete target -->
+        <com.android.launcher2.DeleteDropTarget
+            style="@style/DropTargetButton"
+            android:id="@+id/delete_target_text"
+            android:text="@string/delete_zone_label_workspace"
+            android:drawableLeft="@drawable/remove_target_selector" />
+    </FrameLayout>
+    <FrameLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        style="@style/DropTargetButtonContainer"
+        android:layout_weight="1">
+        <!-- Info target -->
+        <com.android.launcher2.InfoDropTarget
+            style="@style/DropTargetButton"
+            android:id="@+id/info_target_text"
+            android:text="@string/info_target_label"
+            android:drawableLeft="@drawable/info_target_selector" />
+    </FrameLayout>
+</merge>
\ No newline at end of file
diff --git a/res/layout/qsb_bar.xml b/res/layout/qsb_bar.xml
index ad9027f..322dc00 100644
--- a/res/layout/qsb_bar.xml
+++ b/res/layout/qsb_bar.xml
@@ -25,29 +25,9 @@
     <!-- Drag specific targets container -->
     <LinearLayout
         style="@style/SearchDropTargetBar"
-        android:id="@+id/drag_target_bar"
-        android:visibility="gone">
+        android:id="@+id/drag_target_bar">
 
-        <FrameLayout
-            style="@style/DropTargetButtonContainer"
-            android:layout_weight="1">
-            <!-- Delete target -->
-            <com.android.launcher2.DeleteDropTarget
-                style="@style/DropTargetButton"
-                android:id="@+id/delete_target_text"
-                android:text="@string/delete_zone_label_workspace"
-                android:drawableLeft="@drawable/remove_target_selector" />
-        </FrameLayout>
-
-        <FrameLayout
-            style="@style/DropTargetButtonContainer"
-            android:layout_weight="1">
-            <!-- Info target -->
-            <com.android.launcher2.InfoDropTarget
-                style="@style/DropTargetButton"
-                android:id="@+id/info_target_text"
-                android:text="@string/info_target_label"
-                android:drawableLeft="@drawable/info_target_selector" />
-        </FrameLayout>
+        <include
+            layout="@layout/drop_target_bar" />
     </LinearLayout>
 </com.android.launcher2.SearchDropTargetBar>
diff --git a/res/values-land/styles.xml b/res/values-land/styles.xml
index f4519ab..df3356e 100644
--- a/res/values-land/styles.xml
+++ b/res/values-land/styles.xml
@@ -47,10 +47,10 @@
         <item name="android:layout_height">0dp</item>
     </style>
     <style name="DropTargetButton">
-        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_width">wrap_content</item>
         <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_gravity">center_vertical</item>
-        <item name="android:gravity">center_horizontal</item>
+        <item name="android:layout_gravity">center</item>
+        <item name="android:gravity">center</item>
         <item name="android:paddingTop">@dimen/toolbar_button_vertical_padding</item>
         <item name="android:paddingBottom">@dimen/toolbar_button_vertical_padding</item>
         <item name="android:paddingLeft">@dimen/toolbar_button_horizontal_padding</item>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 3b70d4f..fbd743b 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -24,8 +24,9 @@
          that we put on each page for allowing folders to draw out of bounds -->
     <dimen name="qsb_bar_height_inset">34dp</dimen>
     <dimen name="qsb_bar_height">48dp</dimen>
-    <dimen name="qsb_padding_left">12dp</dimen>
-    <dimen name="qsb_padding_right">12dp</dimen>
+    <dimen name="qsb_padding_left">16dp</dimen>
+    <dimen name="qsb_padding_right">16dp</dimen>
+
     <dimen name="search_bar_height">48dp</dimen>
 
 <!-- Hotseat -->
@@ -36,8 +37,8 @@
     <dimen name="button_bar_height">94dip</dimen>
     <dimen name="button_bar_height_bottom_padding">14dp</dimen>
     <dimen name="button_bar_height_top_padding">20dp</dimen>
-    <dimen name="button_bar_width_left_padding">33dp</dimen>
-    <dimen name="button_bar_width_right_padding">33dp</dimen>
+    <dimen name="button_bar_width_left_padding">25dp</dimen>
+    <dimen name="button_bar_width_right_padding">25dp</dimen>
     <dimen name="button_bar_height_plus_padding">104dp</dimen>
 
 <!-- Folders -->
@@ -46,6 +47,11 @@
     <dimen name="folder_cell_width">86dp</dimen>
     <dimen name="folder_cell_height">90dp</dimen>
 
+    <dimen name="cell_layout_left_padding_port">12dp</dimen>
+    <dimen name="cell_layout_right_padding_port">12dp</dimen>
+    <dimen name="workspace_divider_padding_left">19dp</dimen>
+    <dimen name="workspace_divider_padding_right">19dp</dimen>
+
 <!-- AppsCustomize -->
     <dimen name="apps_customize_cell_width">96dp</dimen>
     <dimen name="apps_customize_cell_height">98dp</dimen>
@@ -58,11 +64,11 @@
 
 <!-- Workspace cell size -->
     <dimen name="workspace_cell_width_land">88dp</dimen>
-    <dimen name="workspace_cell_width_port">88dp</dimen>
+    <dimen name="workspace_cell_width_port">96dp</dimen>
     <dimen name="workspace_cell_height_land">88dp</dimen>
-    <dimen name="workspace_cell_height_port">88dp</dimen>
+    <dimen name="workspace_cell_height_port">96dp</dimen>
     <dimen name="workspace_width_gap_land">32dp</dimen>
-    <dimen name="workspace_width_gap_port">6dp</dimen>
+    <dimen name="workspace_width_gap_port">0dp</dimen>
     <dimen name="workspace_height_gap_land">0dp</dimen>
     <dimen name="workspace_height_gap_port">24dp</dimen>
 </resources>
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 8aaa2d9..a3d8f8d 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -279,6 +279,11 @@
         mWidgetPreviewIconPaddedDimension =
             (int) (mAppIconSize * (1 + (2 * sWidgetPreviewIconPaddingPercentage)));
         mFadeInAdjacentScreens = false;
+
+        // Unless otherwise specified this view is important for accessibility.
+        if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+            setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+        }
     }
 
     @Override
diff --git a/src/com/android/launcher2/ButtonDropTarget.java b/src/com/android/launcher2/ButtonDropTarget.java
index e9f8ce8..1c9fa5f 100644
--- a/src/com/android/launcher2/ButtonDropTarget.java
+++ b/src/com/android/launcher2/ButtonDropTarget.java
@@ -20,6 +20,7 @@
 import android.content.res.Resources;
 import android.graphics.PointF;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.widget.TextView;
 
@@ -68,6 +69,16 @@
         mSearchDropTargetBar = searchDropTargetBar;
     }
 
+    protected Drawable getCurrentDrawable() {
+        Drawable[] drawables = getCompoundDrawables();
+        for (int i = 0; i < drawables.length; ++i) {
+            if (drawables[i] != null) {
+                return drawables[i];
+            }
+        }
+        return null;
+    }
+
     public void onDrop(DragObject d) {
     }
 
diff --git a/src/com/android/launcher2/DeleteDropTarget.java b/src/com/android/launcher2/DeleteDropTarget.java
index eb831f6..1edc2ab 100644
--- a/src/com/android/launcher2/DeleteDropTarget.java
+++ b/src/com/android/launcher2/DeleteDropTarget.java
@@ -25,6 +25,7 @@
 import android.content.res.Resources;
 import android.graphics.PointF;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.graphics.drawable.TransitionDrawable;
 import android.util.AttributeSet;
 import android.view.View;
@@ -76,7 +77,7 @@
 
         // The current drawable is set to either the remove drawable or the uninstall drawable 
         // and is initially set to the remove drawable, as set in the layout xml.
-        mCurrentDrawable = (TransitionDrawable) getCompoundDrawables()[0];
+        mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
 
         // Remove the text in the Phone UI in landscape
         int orientation = getResources().getConfiguration().orientation;
@@ -157,7 +158,7 @@
         } else {
             setCompoundDrawablesWithIntrinsicBounds(mRemoveDrawable, null, null, null);
         }
-        mCurrentDrawable = (TransitionDrawable) getCompoundDrawables()[0];
+        mCurrentDrawable = (TransitionDrawable) getCurrentDrawable();
 
         mActive = isVisible;
         resetHoverColor();
diff --git a/src/com/android/launcher2/InfoDropTarget.java b/src/com/android/launcher2/InfoDropTarget.java
index 134f4cb..d6bf5f2 100644
--- a/src/com/android/launcher2/InfoDropTarget.java
+++ b/src/com/android/launcher2/InfoDropTarget.java
@@ -16,7 +16,6 @@
 
 package com.android.launcher2;
 
-import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -51,7 +50,7 @@
         // Get the hover color
         Resources r = getResources();
         mHoverColor = r.getColor(R.color.info_target_hover_tint);
-        mDrawable = (TransitionDrawable) getCompoundDrawables()[0];
+        mDrawable = (TransitionDrawable) getCurrentDrawable();
         mDrawable.setCrossFadeEnabled(true);
 
         // Remove the text in the Phone UI in landscape
diff --git a/src/com/android/launcher2/LauncherProvider.java b/src/com/android/launcher2/LauncherProvider.java
index 4cf87d2..0720259 100644
--- a/src/com/android/launcher2/LauncherProvider.java
+++ b/src/com/android/launcher2/LauncherProvider.java
@@ -66,7 +66,7 @@
 
     private static final String DATABASE_NAME = "launcher.db";
 
-    private static final int DATABASE_VERSION = 11;
+    private static final int DATABASE_VERSION = 12;
 
     static final String AUTHORITY = "com.android.launcher2.settings";
 
@@ -203,7 +203,7 @@
         return mOpenHelper.generateNewId();
     }
 
-    public void loadDefaultFavoritesIfNecessary() {
+    synchronized public void loadDefaultFavoritesIfNecessary() {
         String spKey = LauncherApplication.getSharedPreferencesKey();
         SharedPreferences sp = getContext().getSharedPreferences(spKey, Context.MODE_PRIVATE);
         if (sp.getBoolean(DB_CREATED_BUT_DEFAULT_WORKSPACE_NOT_LOADED, false)) {
@@ -477,14 +477,15 @@
                 version = 9;
             }
 
-            // We bumped the version twice during JB, once to update the launch flags, and once to
-            // update the override for the default launch animation.
-            if (version < 11) {
+            // We bumped the version three time during JB, once to update the launch flags, once to
+            // update the override for the default launch animation and once to set the mimetype
+            // to improve startup performance
+            if (version < 12) {
                 // Contact shortcuts need a different set of flags to be launched now
                 // The updateContactsShortcuts change is idempotent, so we can keep using it like
                 // back in the Donut days
                 updateContactsShortcuts(db);
-                version = 11;
+                version = 12;
             }
 
             if (version != DATABASE_VERSION) {
@@ -540,6 +541,9 @@
                                     newIntent.putExtra(
                                             Launcher.INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION, true);
                                     newIntent.setData(uri);
+                                    // Determine the type and also put that in the shortcut
+                                    // (that can speed up launch a bit)
+                                    newIntent.setDataAndType(uri, newIntent.resolveType(mContext));
 
                                     final ContentValues values = new ContentValues();
                                     values.put(LauncherSettings.Favorites.INTENT,
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index a9603ac..93725ce 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -24,6 +24,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.Rect;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.AttributeSet;
@@ -1857,7 +1858,13 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
-        info.setScrollable(true);
+        info.setScrollable(getPageCount() > 1);
+        if (getCurrentPage() < getPageCount() - 1) {
+            info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+        }
+        if (getCurrentPage() > 0) {
+            info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+        }
     }
 
     @Override
@@ -1871,6 +1878,28 @@
         }
     }
 
+    @Override
+    public boolean performAccessibilityAction(int action, Bundle arguments) {
+        if (super.performAccessibilityAction(action, arguments)) {
+            return true;
+        }
+        switch (action) {
+            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+                if (getCurrentPage() < getPageCount() - 1) {
+                    scrollRight();
+                    return true;
+                }
+            } break;
+            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+                if (getCurrentPage() > 0) {
+                    scrollLeft();
+                    return true;
+                }
+            } break;
+        }
+        return false;
+    }
+
     protected String getCurrentPageDescription() {
         return String.format(getContext().getString(R.string.default_scroll_format),
                  getNextPage() + 1, getChildCount());
diff --git a/src/com/android/launcher2/PreloadReceiver.java b/src/com/android/launcher2/PreloadReceiver.java
new file mode 100644
index 0000000..d1bc639
--- /dev/null
+++ b/src/com/android/launcher2/PreloadReceiver.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 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.launcher2;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+public class PreloadReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        final LauncherApplication app = (LauncherApplication) context.getApplicationContext();
+        final LauncherProvider provider = app.getLauncherProvider();
+        if (provider != null) {
+            new Thread(new Runnable() {
+                public void run() {
+                    provider.loadDefaultFavoritesIfNecessary();
+                }
+            }).start();
+        }
+    }
+}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index d15d318..00684bd 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -342,6 +342,11 @@
 
         // Disable multitouch across the workspace/all apps/customize tray
         setMotionEventSplittingEnabled(true);
+
+        // Unless otherwise specified this view is important for accessibility.
+        if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+            setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+        }
     }
 
     // estimate the size of a widget with spans hSpan, vSpan. return MAX_VALUE for each