Merge "Initializing the Add To Homescreen setting by reading it from market app" into ub-launcher3-dorval
diff --git a/res/layout/system_shortcut.xml b/res/layout/system_shortcut.xml
index 113b1be..dae9b5e 100644
--- a/res/layout/system_shortcut.xml
+++ b/res/layout/system_shortcut.xml
@@ -30,6 +30,7 @@
         android:paddingEnd="@dimen/popup_padding_end"
         android:textSize="14sp"
         android:fontFamily="sans-serif"
+        launcher:iconDisplay="shortcut_popup"
         launcher:layoutHorizontal="true" />
 
     <View
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index 34adf47..0608fdd 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -19,6 +19,8 @@
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
+import android.graphics.Rect;
+import android.os.Bundle;
 import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -60,6 +62,11 @@
      */
     public static boolean startDetailsActivityForInfo(
             ItemInfo info, Launcher launcher, DropTargetResultCallback callback) {
+        return startDetailsActivityForInfo(info, launcher, callback, null, null);
+    }
+
+    public static boolean startDetailsActivityForInfo(ItemInfo info, Launcher launcher,
+            DropTargetResultCallback callback, Rect sourceBounds, Bundle opts) {
         boolean result = false;
         ComponentName componentName = null;
         if (info instanceof AppInfo) {
@@ -74,7 +81,7 @@
         if (componentName != null) {
             try {
                 LauncherAppsCompat.getInstance(launcher)
-                        .showAppDetailsForProfile(componentName, info.user);
+                        .showAppDetailsForProfile(componentName, info.user, sourceBounds, opts);
                 result = true;
             } catch (SecurityException | ActivityNotFoundException e) {
                 Toast.makeText(launcher, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3c29f5e..27b8859 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2668,7 +2668,7 @@
     }
 
     @TargetApi(Build.VERSION_CODES.M)
-    private Bundle getActivityLaunchOptions(View v) {
+    public Bundle getActivityLaunchOptions(View v) {
         if (Utilities.ATLEAST_MARSHMALLOW) {
             int left = 0, top = 0;
             int width = v.getMeasuredWidth(), height = v.getMeasuredHeight();
@@ -2694,7 +2694,7 @@
         return null;
     }
 
-    private Rect getViewBounds(View v) {
+    public Rect getViewBounds(View v) {
         int[] pos = new int[2];
         v.getLocationOnScreen(pos);
         return new Rect(pos[0], pos[1], pos[0] + v.getWidth(), pos[1] + v.getHeight());
@@ -3902,6 +3902,7 @@
         // Update AllApps
         if (mAppsView != null) {
             mAppsView.removeApps(appInfos);
+            tryAndUpdatePredictedApps();
         }
     }
 
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index f17d8de..e997a99 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -78,7 +78,8 @@
             Rect sourceBounds, Bundle opts);
     public abstract ApplicationInfo getApplicationInfo(
             String packageName, int flags, UserHandle user);
-    public abstract void showAppDetailsForProfile(ComponentName component, UserHandle user);
+    public abstract void showAppDetailsForProfile(ComponentName component, UserHandle user,
+            Rect sourceBounds, Bundle opts);
     public abstract void addOnAppsChangedCallback(OnAppsChangedCallbackCompat listener);
     public abstract void removeOnAppsChangedCallback(OnAppsChangedCallbackCompat listener);
     public abstract boolean isPackageEnabledForProfile(String packageName, UserHandle user);
@@ -142,4 +143,8 @@
             return null;
         }
     }
+
+    public void showAppDetailsForProfile(ComponentName component, UserHandle user) {
+        showAppDetailsForProfile(component, user, null, null);
+    }
 }
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
index 58683db..647c315 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompatVL.java
@@ -95,8 +95,9 @@
     }
 
     @Override
-    public void showAppDetailsForProfile(ComponentName component, UserHandle user) {
-        mLauncherApps.startAppDetailsActivity(component, user, null, null);
+    public void showAppDetailsForProfile(ComponentName component, UserHandle user,
+            Rect sourceBounds, Bundle opts) {
+        mLauncherApps.startAppDetailsActivity(component, user, sourceBounds, opts);
     }
 
     @Override
diff --git a/src/com/android/launcher3/notification/NotificationItemView.java b/src/com/android/launcher3/notification/NotificationItemView.java
index 5e8e2c7..e5bf35a 100644
--- a/src/com/android/launcher3/notification/NotificationItemView.java
+++ b/src/com/android/launcher3/notification/NotificationItemView.java
@@ -76,6 +76,11 @@
         mSwipeHelper.setDisableHardwareLayers(true);
     }
 
+    public int getHeightMinusFooter() {
+        int footerHeight = mFooter.getParent() == null ? 0 : mFooter.getHeight();
+        return getHeight() - footerHeight;
+    }
+
     public Animator animateHeightRemoval(int heightToRemove) {
         final int newHeight = getHeight() - heightToRemove;
         return new PillHeightRevealOutlineProvider(mPillRect,
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index cb37f08..8dca699 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -232,8 +232,8 @@
         boolean isGroupHeader = (notification.flags & Notification.FLAG_GROUP_SUMMARY) != 0;
         CharSequence title = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
         CharSequence text = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
-        boolean missingTitleOrText = TextUtils.isEmpty(title) || TextUtils.isEmpty(text);
-        return (notification.contentIntent == null || isGroupHeader || missingTitleOrText);
+        boolean missingTitleAndText = TextUtils.isEmpty(title) && TextUtils.isEmpty(text);
+        return (isGroupHeader || missingTitleAndText);
     }
 
     public interface NotificationsChangedListener {
diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java
index bb2dac0..d6e0272 100644
--- a/src/com/android/launcher3/notification/NotificationMainView.java
+++ b/src/com/android/launcher3/notification/NotificationMainView.java
@@ -21,6 +21,7 @@
 import android.content.res.ColorStateList;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.RippleDrawable;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 import android.view.View;
@@ -83,11 +84,21 @@
     public void applyNotificationInfo(NotificationInfo mainNotification, View iconView,
            boolean animate) {
         mNotificationInfo = mainNotification;
-        mTitleView.setText(mNotificationInfo.title);
-        mTextView.setText(mNotificationInfo.text);
+        CharSequence title = mNotificationInfo.title;
+        CharSequence text = mNotificationInfo.text;
+        if (!TextUtils.isEmpty(title) && !TextUtils.isEmpty(text)) {
+            mTitleView.setText(title);
+            mTextView.setText(text);
+        } else {
+            mTitleView.setMaxLines(2);
+            mTitleView.setText(TextUtils.isEmpty(title) ? text : title);
+            mTextView.setVisibility(GONE);
+        }
         iconView.setBackground(mNotificationInfo.getIconForBackground(getContext(),
                 mBackgroundColor));
-        setOnClickListener(mNotificationInfo);
+        if (mNotificationInfo.intent != null) {
+            setOnClickListener(mNotificationInfo);
+        }
         setTranslationX(0);
         // Add a dummy ItemInfo so that logging populates the correct container and item types
         // instead of DEFAULT_CONTAINERTYPE and DEFAULT_ITEMTYPE, respectively.
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index dc7fa05..fb7f80c 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -107,6 +107,7 @@
 
     protected Animator mOpenCloseAnimator;
     private boolean mDeferContainerRemoval;
+    private AnimatorSet mReduceHeightAnimatorSet;
 
     public PopupContainerWithArrow(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
@@ -584,7 +585,7 @@
                     R.integer.config_removeNotificationViewDuration);
             final int spacing = getResources().getDimensionPixelSize(R.dimen.popup_items_spacing);
             removeNotification.play(reduceNotificationViewHeight(
-                    mNotificationItemView.getHeight() + spacing, duration));
+                    mNotificationItemView.getHeightMinusFooter() + spacing, duration));
             final View removeMarginView = mIsAboveIcon ? getItemViewAt(getItemCount() - 2)
                     : mNotificationItemView;
             if (removeMarginView != null) {
@@ -642,9 +643,12 @@
      * Animates the height of the notification item and the translationY of other items accordingly.
      */
     public Animator reduceNotificationViewHeight(int heightToRemove, int duration) {
+        if (mReduceHeightAnimatorSet != null) {
+            mReduceHeightAnimatorSet.cancel();
+        }
         final int translateYBy = mIsAboveIcon ? heightToRemove : -heightToRemove;
-        AnimatorSet animatorSet = LauncherAnimUtils.createAnimatorSet();
-        animatorSet.play(mNotificationItemView.animateHeightRemoval(heightToRemove));
+        mReduceHeightAnimatorSet = LauncherAnimUtils.createAnimatorSet();
+        mReduceHeightAnimatorSet.play(mNotificationItemView.animateHeightRemoval(heightToRemove));
         PropertyResetListener<View, Float> resetTranslationYListener
                 = new PropertyResetListener<>(TRANSLATION_Y, 0f);
         for (int i = 0; i < getItemCount(); i++) {
@@ -656,20 +660,21 @@
             ValueAnimator translateItem = ObjectAnimator.ofFloat(itemView, TRANSLATION_Y,
                     itemView.getTranslationY() + translateYBy).setDuration(duration);
             translateItem.addListener(resetTranslationYListener);
-            animatorSet.play(translateItem);
+            mReduceHeightAnimatorSet.play(translateItem);
         }
-        if (mIsAboveIcon) {
-            // All the items, including the notification item, translated down, but the
-            // container itself did not. This means the items would jump back to their
-            // original translation unless we update the container's translationY here.
-            animatorSet.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
+        mReduceHeightAnimatorSet.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                if (mIsAboveIcon) {
+                    // All the items, including the notification item, translated down, but the
+                    // container itself did not. This means the items would jump back to their
+                    // original translation unless we update the container's translationY here.
                     setTranslationY(getTranslationY() + translateYBy);
                 }
-            });
-        }
-        return animatorSet;
+                mReduceHeightAnimatorSet = null;
+            }
+        });
+        return mReduceHeightAnimatorSet;
     }
 
     @Override
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index e48e349..f158f71 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -1,9 +1,12 @@
 package com.android.launcher3.popup;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
 import android.view.View;
 
+import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.InfoDropTarget;
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.Launcher;
@@ -60,7 +63,7 @@
             return new View.OnClickListener() {
                 @Override
                 public void onClick(View view) {
-                    PopupContainerWithArrow.getOpen(launcher).close(true);
+                    AbstractFloatingView.closeAllOpenViews(launcher);
                     WidgetsBottomSheet widgetsBottomSheet =
                             (WidgetsBottomSheet) launcher.getLayoutInflater().inflate(
                                     R.layout.widgets_bottom_sheet, launcher.getDragLayer(), false);
@@ -81,7 +84,9 @@
             return new View.OnClickListener() {
                 @Override
                 public void onClick(View view) {
-                    InfoDropTarget.startDetailsActivityForInfo(itemInfo, launcher, null);
+                    Rect sourceBounds = launcher.getViewBounds(view);
+                    Bundle opts = launcher.getActivityLaunchOptions(view);
+                    InfoDropTarget.startDetailsActivityForInfo(itemInfo, launcher, null, sourceBounds, opts);
                 }
             };
         }