Merge "Import translations. DO NOT MERGE" into ub-launcher3-master
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 5938fba..53d9385 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -717,6 +717,16 @@
                 if (DEBUG_LOADERS) Log.d(TAG, "step 3.2: bind deep shortcuts");
                 bindDeepShortcuts();
 
+                // Take a break
+                if (DEBUG_LOADERS) Log.d(TAG, "step 3 completed, wait for idle");
+                waitForIdle();
+                verifyNotStopped();
+
+                // fourth step
+                if (DEBUG_LOADERS) Log.d(TAG, "step 4.1: loading widgets");
+                refreshAndBindWidgetsAndShortcuts(getCallback(), false /* bindFirst */,
+                        null /* packageUser */);
+
                 synchronized (mLock) {
                     // Everything loaded bind the data.
                     mModelLoaded = true;
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 0a2ec2a..9a91583 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -30,6 +30,7 @@
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherAppWidgetInfo;
+import com.android.launcher3.LauncherModel;
 import com.android.launcher3.LauncherModel.CallbackTask;
 import com.android.launcher3.LauncherModel.Callbacks;
 import com.android.launcher3.LauncherSettings;
@@ -44,6 +45,7 @@
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.ManagedProfileHeuristic;
 import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.PackageUserKey;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -370,6 +372,14 @@
                     callbacks.notifyWidgetProvidersChanged();
                 }
             });
+        } else if (Utilities.isAtLeastO() && mOp == OP_ADD) {
+            // Load widgets for the new package.
+            for (int i = 0; i < N; i++) {
+                LauncherModel model = app.getModel();
+                model.refreshAndBindWidgetsAndShortcuts(
+                        model.getCallback(), false /* bindFirst */,
+                        new PackageUserKey(packages[i], mUser) /* packageUser */);
+            }
         }
     }
 }
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 5891085..a4823ae 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -146,21 +146,24 @@
             return null;
         }
 
-        List<String> shortcutIds = launcher.getPopupDataProvider().getShortcutIdsForItem(itemInfo);
-        List<NotificationKeyData> notificationKeys = launcher.getPopupDataProvider()
+        PopupDataProvider popupDataProvider = launcher.getPopupDataProvider();
+        List<String> shortcutIds = popupDataProvider.getShortcutIdsForItem(itemInfo);
+        List<NotificationKeyData> notificationKeys = popupDataProvider
                 .getNotificationKeysForItem(itemInfo);
+        List<SystemShortcut> systemShortcuts = popupDataProvider
+                .getEnabledSystemShortcutsForItem(itemInfo);
 
         final PopupContainerWithArrow container =
                 (PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
                         R.layout.popup_container, launcher.getDragLayer(), false);
         container.setVisibility(View.INVISIBLE);
         launcher.getDragLayer().addView(container);
-        container.populateAndShow(icon, shortcutIds, notificationKeys);
+        container.populateAndShow(icon, shortcutIds, notificationKeys, systemShortcuts);
         return container;
     }
 
     public void populateAndShow(final BubbleTextView originalIcon, final List<String> shortcutIds,
-            final List<NotificationKeyData> notificationKeys) {
+            final List<NotificationKeyData> notificationKeys, List<SystemShortcut> systemShortcuts) {
         final Resources resources = getResources();
         final int arrowWidth = resources.getDimensionPixelSize(R.dimen.popup_arrow_width);
         final int arrowHeight = resources.getDimensionPixelSize(R.dimen.popup_arrow_height);
@@ -171,7 +174,7 @@
 
         // Add dummy views first, and populate with real info when ready.
         PopupPopulator.Item[] itemsToPopulate = PopupPopulator
-                .getItemsToPopulate(shortcutIds, notificationKeys);
+                .getItemsToPopulate(shortcutIds, notificationKeys, systemShortcuts);
         addDummyViews(originalIcon, itemsToPopulate, notificationKeys.size() > 1);
 
         measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
@@ -218,7 +221,7 @@
         new Handler(workerLooper).postAtFrontOfQueue(PopupPopulator.createUpdateRunnable(
                 mLauncher, originalItemInfo, new Handler(Looper.getMainLooper()),
                 this, shortcutIds, shortcutViews, notificationKeys, mNotificationItemView,
-                systemShortcutViews));
+                systemShortcuts, systemShortcutViews));
     }
 
     private void addDummyViews(BubbleTextView originalIcon,
@@ -624,12 +627,9 @@
 
     @Override
     protected void onWidgetsBound() {
-        enableWidgets();
-    }
-
-    public boolean enableWidgets() {
-        return mShortcutsItemView != null && mShortcutsItemView.enableWidgets(
-                (ItemInfo) mOriginalIcon.getTag());
+        if (mShortcutsItemView != null) {
+            mShortcutsItemView.enableWidgetsIfExist(mOriginalIcon);
+        }
     }
 
     private ObjectAnimator createArrowScaleAnim(float scale) {
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index c1a9ba1..eaceaa9 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -33,6 +33,7 @@
 import com.android.launcher3.util.MultiHashMap;
 import com.android.launcher3.util.PackageUserKey;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -49,7 +50,7 @@
     private static final String TAG = "PopupDataProvider";
 
     /** Note that these are in order of priority. */
-    public static final SystemShortcut[] SYSTEM_SHORTCUTS = new SystemShortcut[] {
+    private static final SystemShortcut[] SYSTEM_SHORTCUTS = new SystemShortcut[] {
             new SystemShortcut.AppInfo(),
             new SystemShortcut.Widgets(),
     };
@@ -240,6 +241,16 @@
                 : notificationListener.getNotificationsForKeys(notificationKeys);
     }
 
+    public @NonNull List<SystemShortcut> getEnabledSystemShortcutsForItem(ItemInfo info) {
+        List<SystemShortcut> systemShortcuts = new ArrayList<>();
+        for (SystemShortcut systemShortcut : SYSTEM_SHORTCUTS) {
+            if (systemShortcut.getOnClickListener(mLauncher, info) != null) {
+                systemShortcuts.add(systemShortcut);
+            }
+        }
+        return systemShortcuts;
+    }
+
     public void cancelNotification(String notificationKey) {
         NotificationListener notificationListener = NotificationListener.getInstanceIfConnected();
         if (notificationListener == null) {
diff --git a/src/com/android/launcher3/popup/PopupPopulator.java b/src/com/android/launcher3/popup/PopupPopulator.java
index 3ba4eba..fd00105 100644
--- a/src/com/android/launcher3/popup/PopupPopulator.java
+++ b/src/com/android/launcher3/popup/PopupPopulator.java
@@ -72,7 +72,8 @@
     }
 
     public static @NonNull Item[] getItemsToPopulate(@NonNull List<String> shortcutIds,
-            @NonNull List<NotificationKeyData> notificationKeys) {
+            @NonNull List<NotificationKeyData> notificationKeys,
+            @NonNull List<SystemShortcut> systemShortcuts) {
         boolean hasNotifications = notificationKeys.size() > 0;
         int numNotificationItems = hasNotifications ? 1 : 0;
         int numShortcuts = shortcutIds.size();
@@ -80,7 +81,7 @@
             numShortcuts = MAX_SHORTCUTS_IF_NOTIFICATIONS;
         }
         int numItems = Math.min(MAX_ITEMS, numShortcuts + numNotificationItems)
-                + PopupDataProvider.SYSTEM_SHORTCUTS.length;
+                + systemShortcuts.size();
         Item[] items = new Item[numItems];
         for (int i = 0; i < numItems; i++) {
             items[i] = Item.SHORTCUT;
@@ -91,7 +92,7 @@
         }
         // The system shortcuts are always last.
         boolean iconsOnly = !shortcutIds.isEmpty();
-        for (int i = 0; i < PopupDataProvider.SYSTEM_SHORTCUTS.length; i++) {
+        for (int i = 0; i < systemShortcuts.size(); i++) {
             items[numItems - 1 - i] = iconsOnly ? Item.SYSTEM_SHORTCUT_ICON : Item.SYSTEM_SHORTCUT;
         }
         return items;
@@ -182,7 +183,8 @@
             final Handler uiHandler, final PopupContainerWithArrow container,
             final List<String> shortcutIds, final List<DeepShortcutView> shortcutViews,
             final List<NotificationKeyData> notificationKeys,
-            final NotificationItemView notificationView, final List<View> systemShortcutViews) {
+            final NotificationItemView notificationView, final List<SystemShortcut> systemShortcuts,
+            final List<View> systemShortcutViews) {
         final ComponentName activity = originalInfo.getTargetComponent();
         final UserHandle user = originalInfo.user;
         return new Runnable() {
@@ -217,8 +219,8 @@
 
                 // This ensures that mLauncher.getWidgetsForPackageUser()
                 // doesn't return null (it puts all the widgets in memory).
-                for (int i = 0; i < PopupDataProvider.SYSTEM_SHORTCUTS.length; i++) {
-                    final SystemShortcut systemShortcut = PopupDataProvider.SYSTEM_SHORTCUTS[i];
+                for (int i = 0; i < systemShortcuts.size(); i++) {
+                    final SystemShortcut systemShortcut = systemShortcuts.get(i);
                     uiHandler.post(new UpdateSystemShortcutChild(container,
                             systemShortcutViews.get(i), systemShortcut, launcher, originalInfo));
                 }
@@ -274,7 +276,6 @@
 
     /** Updates the system shortcut child based on the given shortcut info. */
     private static class UpdateSystemShortcutChild implements Runnable {
-        private static final float DISABLED_ALPHA = 0.38f;
 
         private final PopupContainerWithArrow mContainer;
         private final View mSystemShortcutChild;
@@ -294,29 +295,24 @@
         @Override
         public void run() {
             final Context context = mSystemShortcutChild.getContext();
-            if (mSystemShortcutChild instanceof DeepShortcutView) {
-                // Expanded system shortcut, with both icon and text shown on white background.
-                final DeepShortcutView shortcutView = (DeepShortcutView) mSystemShortcutChild;
-                shortcutView.getIconView().setBackground(mSystemShortcutInfo.getIcon(context));
-                shortcutView.getBubbleText().setText(mSystemShortcutInfo.getLabel(context));
-            } else if (mSystemShortcutChild instanceof ImageView) {
-                // Only the system shortcut icon shows on a gray background header.
-                final ImageView shortcutIcon = (ImageView) mSystemShortcutChild;
-                shortcutIcon.setImageDrawable(mSystemShortcutInfo.getIcon(context));
-                shortcutIcon.setContentDescription(mSystemShortcutInfo.getLabel(context));
-            }
-            if (!(mSystemShortcutInfo instanceof SystemShortcut.Widgets)) {
-                mSystemShortcutChild.setOnClickListener(mSystemShortcutInfo
-                        .getOnClickListener(mLauncher, mItemInfo));
-            } else {
-                mSystemShortcutChild.setTag(mSystemShortcutInfo);
-                // Widgets might not be enabled right away.
-                if (mContainer.enableWidgets()) {
-                    return;
-                }
-                // Disable Widgets (we might be able to re-enable when widgets are bound).
-                mSystemShortcutChild.setAlpha(DISABLED_ALPHA);
-            }
+            initializeSystemShortcut(context, mSystemShortcutChild, mSystemShortcutInfo);
+            mSystemShortcutChild.setOnClickListener(mSystemShortcutInfo
+                    .getOnClickListener(mLauncher, mItemInfo));
         }
     }
+
+    public static void initializeSystemShortcut(Context context, View view, SystemShortcut info) {
+        if (view instanceof DeepShortcutView) {
+            // Expanded system shortcut, with both icon and text shown on white background.
+            final DeepShortcutView shortcutView = (DeepShortcutView) view;
+            shortcutView.getIconView().setBackground(info.getIcon(context));
+            shortcutView.getBubbleText().setText(info.getLabel(context));
+        } else if (view instanceof ImageView) {
+            // Only the system shortcut icon shows on a gray background header.
+            final ImageView shortcutIcon = (ImageView) view;
+            shortcutIcon.setImageDrawable(info.getIcon(context));
+            shortcutIcon.setContentDescription(info.getLabel(context));
+        }
+        view.setTag(info);
+    }
 }
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 7d86163..9caf98c 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -41,7 +41,6 @@
     public abstract View.OnClickListener getOnClickListener(final Launcher launcher,
             final ItemInfo itemInfo);
 
-
     public static class Widgets extends SystemShortcut {
 
         public Widgets() {
diff --git a/src/com/android/launcher3/shortcuts/ShortcutsItemView.java b/src/com/android/launcher3/shortcuts/ShortcutsItemView.java
index 1f90bb0..ee64b98 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutsItemView.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutsItemView.java
@@ -26,6 +26,7 @@
 import android.widget.LinearLayout;
 
 import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAnimUtils;
@@ -119,6 +120,10 @@
     }
 
     public void addShortcutView(View shortcutView, PopupPopulator.Item shortcutType) {
+        addShortcutView(shortcutView, shortcutType, -1);
+    }
+
+    private void addShortcutView(View shortcutView, PopupPopulator.Item shortcutType, int index) {
         if (shortcutType == PopupPopulator.Item.SHORTCUT) {
             mDeepShortcutViews.add((DeepShortcutView) shortcutView);
         } else {
@@ -131,7 +136,7 @@
                         R.layout.system_shortcut_icons, mShortcutsLayout, false);
                 mShortcutsLayout.addView(mSystemShortcutIcons, 0);
             }
-            mSystemShortcutIcons.addView(shortcutView);
+            mSystemShortcutIcons.addView(shortcutView, index);
         } else {
             if (mShortcutsLayout.getChildCount() > 0) {
                 View prevChild = mShortcutsLayout.getChildAt(mShortcutsLayout.getChildCount() - 1);
@@ -139,7 +144,7 @@
                     prevChild.findViewById(R.id.divider).setVisibility(VISIBLE);
                 }
             }
-            mShortcutsLayout.addView(shortcutView);
+            mShortcutsLayout.addView(shortcutView, index);
         }
     }
 
@@ -160,24 +165,47 @@
     }
 
     /**
-     * Sets the onClickListener on widgets system shortcut child, and updates alpha to 1.
-     * @return whether widgets is enabled, i.e. the onClickListener is not null.
+     * Adds a {@link SystemShortcut.Widgets} item if there are widgets for the given ItemInfo.
      */
-    public boolean enableWidgets(ItemInfo itemInfo) {
-        for (View systemShortcut : mSystemShortcutViews) {
-            if (systemShortcut.getTag() instanceof SystemShortcut.Widgets) {
-                View.OnClickListener onClickListener =
-                        ((SystemShortcut.Widgets) systemShortcut.getTag()).getOnClickListener(
-                                mLauncher, itemInfo);
-                if (onClickListener != null) {
-                    systemShortcut.setAlpha(1f);
-                    systemShortcut.setOnClickListener(onClickListener);
-                    return true;
-                }
-                return false;
+    public void enableWidgetsIfExist(final BubbleTextView originalIcon) {
+        ItemInfo itemInfo = (ItemInfo) originalIcon.getTag();
+        SystemShortcut widgetInfo = new SystemShortcut.Widgets();
+        View.OnClickListener onClickListener = widgetInfo.getOnClickListener(mLauncher, itemInfo);
+        View widgetsView = null;
+        for (View systemShortcutView : mSystemShortcutViews) {
+            if (systemShortcutView.getTag() instanceof SystemShortcut.Widgets) {
+                widgetsView = systemShortcutView;
+                break;
             }
         }
-        return false;
+        final PopupPopulator.Item widgetsItem = mSystemShortcutIcons == null
+                ? PopupPopulator.Item.SYSTEM_SHORTCUT
+                : PopupPopulator.Item.SYSTEM_SHORTCUT_ICON;
+        if (onClickListener != null && widgetsView == null) {
+            // We didn't have any widgets cached but now there are some, so enable the shortcut.
+            widgetsView = mLauncher.getLayoutInflater().inflate(widgetsItem.layoutId, this, false);
+            PopupPopulator.initializeSystemShortcut(getContext(), widgetsView, widgetInfo);
+            widgetsView.setOnClickListener(onClickListener);
+            if (widgetsItem == PopupPopulator.Item.SYSTEM_SHORTCUT_ICON) {
+                addShortcutView(widgetsView, widgetsItem, 0);
+            } else {
+                // If using the expanded system shortcut (as opposed to just the icon), we need to
+                // reopen the container to ensure measurements etc. all work out. While this could
+                // be quite janky, in practice the user would typically see a small flicker as the
+                // animation restarts partway through, and this is a very rare edge case anyway.
+                ((PopupContainerWithArrow) getParent()).close(false);
+                PopupContainerWithArrow.showForIcon(originalIcon);
+            }
+        } else if (onClickListener == null && widgetsView != null) {
+            // No widgets exist, but we previously added the shortcut so remove it.
+            if (widgetsItem == PopupPopulator.Item.SYSTEM_SHORTCUT_ICON) {
+                mSystemShortcutViews.remove(widgetsView);
+                mSystemShortcutIcons.removeView(widgetsView);
+            } else {
+                ((PopupContainerWithArrow) getParent()).close(false);
+                PopupContainerWithArrow.showForIcon(originalIcon);
+            }
+        }
     }
 
     @Override