Merge "Making some methods accessible" into ub-launcher3-dorval-polish
diff --git a/proguard.flags b/proguard.flags
index 2ad9cac..51abcca 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -98,3 +98,7 @@
 -keep interface com.android.launcher3.userevent.nano.LauncherLogProto.** {
   *;
 }
+
+-keep interface com.android.launcher3.model.nano.LauncherDumpProto.** {
+  *;
+}
diff --git a/res/layout/system_shortcut.xml b/res/layout/system_shortcut.xml
index 0952703..6f702f6 100644
--- a/res/layout/system_shortcut.xml
+++ b/res/layout/system_shortcut.xml
@@ -33,7 +33,8 @@
         android:textColor="?android:attr/textColorPrimary"
         android:fontFamily="sans-serif"
         launcher:iconDisplay="shortcut_popup"
-        launcher:layoutHorizontal="true" />
+        launcher:layoutHorizontal="true"
+        android:focusable="false" />
 
     <View
         android:id="@+id/icon"
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 47bc5b5..f4cd8c8 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -35,6 +35,8 @@
     <color name="popup_background_color">#FFF</color>
     <color name="notification_icon_default_color">#757575</color> <!-- Gray 600 -->
     <color name="notification_color_beneath">#E0E0E0</color> <!-- Gray 300 -->
+    <color name="badge_color">#1DE9B6</color> <!-- Teal A400 -->
+    <color name="system_shortcuts_icon_color">@android:color/tertiary_text_light</color>
 
     <color name="icon_background">#E0E0E0</color> <!-- Gray 300 -->
     <color name="legacy_icon_background">#FFFFFF</color>
diff --git a/res/values/config.xml b/res/values/config.xml
index ace1d7e..8f2590a 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -138,4 +138,5 @@
     <item type="id" name="action_move_screen_forwards" />
     <item type="id" name="action_resize" />
     <item type="id" name="action_deep_shortcuts" />
+    <item type="id" name="action_dismiss_notification" />
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f7c4825..1fe33ae 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -292,5 +292,13 @@
 
     <!-- Accessibility description for the shortcuts menu shown for an app. -->
     <string name="shortcuts_menu_description"><xliff:g id="number_of_shortcuts" example="3">%1$d</xliff:g> shortcuts for <xliff:g id="app_name" example="Messenger">%2$s</xliff:g></string>
+    <!-- Accessibility description when the shortcuts menu has notifications as well as shortcuts. -->
+    <string name="shortcuts_menu_with_notifications_description"><xliff:g id="number_of_shortcuts" example="3">%1$d</xliff:g> shortcuts and <xliff:g id="number_of_notifications" example="3">%2$d</xliff:g> notifications for <xliff:g id="app_name" example="Messenger">%3$s</xliff:g></string>
+
+    <!-- Accessibility action to dismiss a notification in the shortcuts menu for an icon. [CHAR_LIMIT=30] -->
+    <string name="action_dismiss_notification">Dismiss</string>
+
+    <!-- Accessibility confirmation for notification being dismissed. -->
+    <string name="notification_dismissed">Notification dismissed</string>
 
 </resources>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 07236d6a..e49ead0 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -457,7 +457,7 @@
             final int scrollX = getScrollX();
             final int scrollY = getScrollY();
             canvas.translate(scrollX, scrollY);
-            mBadgeRenderer.draw(canvas, mIconPalette, mBadgeInfo, mTempIconBounds, mBadgeScale,
+            mBadgeRenderer.draw(canvas, mBadgeInfo, mTempIconBounds, mBadgeScale,
                     mTempSpaceForBadgeOffset);
             canvas.translate(-scrollX, -scrollY);
         }
@@ -674,14 +674,6 @@
         }
     }
 
-    /**
-     * Returns true if the view can show custom shortcuts.
-     */
-    public boolean hasDeepShortcuts() {
-        return !mLauncher.getPopupDataProvider().getShortcutIdsForItem((ItemInfo) getTag())
-                .isEmpty();
-    }
-
     public int getIconSize() {
         return mIconSize;
     }
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 4be25bb..f4342a2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -4054,8 +4054,8 @@
             shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.custom_actions),
                     KeyEvent.KEYCODE_O, KeyEvent.META_CTRL_ON));
         }
-        if (currentFocus instanceof BubbleTextView &&
-                ((BubbleTextView) currentFocus).hasDeepShortcuts()) {
+        if (currentFocus.getTag() instanceof ItemInfo
+                && DeepShortcutManager.supportsShortcuts((ItemInfo) currentFocus.getTag())) {
             shortcutInfos.add(new KeyboardShortcutInfo(getString(R.string.action_deep_shortcut),
                     KeyEvent.KEYCODE_S, KeyEvent.META_CTRL_ON));
         }
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index e2311b5..12789c5 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1777,17 +1777,15 @@
         }
 
         private void loadDeepShortcuts() {
-            if (!mModelLoaded) {
-                sBgDataModel.deepShortcutMap.clear();
-                DeepShortcutManager shortcutManager = DeepShortcutManager.getInstance(mContext);
-                mHasShortcutHostPermission = shortcutManager.hasHostPermission();
-                if (mHasShortcutHostPermission) {
-                    for (UserHandle user : mUserManager.getUserProfiles()) {
-                        if (mUserManager.isUserUnlocked(user)) {
-                            List<ShortcutInfoCompat> shortcuts =
-                                    shortcutManager.queryForAllShortcuts(user);
-                            sBgDataModel.updateDeepShortcutMap(null, user, shortcuts);
-                        }
+            sBgDataModel.deepShortcutMap.clear();
+            DeepShortcutManager shortcutManager = DeepShortcutManager.getInstance(mContext);
+            mHasShortcutHostPermission = shortcutManager.hasHostPermission();
+            if (mHasShortcutHostPermission) {
+                for (UserHandle user : mUserManager.getUserProfiles()) {
+                    if (mUserManager.isUserUnlocked(user)) {
+                        List<ShortcutInfoCompat> shortcuts =
+                                shortcutManager.queryForAllShortcuts(user);
+                        sBgDataModel.updateDeepShortcutMap(null, user, shortcuts);
                     }
                 }
             }
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index e8127c4..3433533 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -36,6 +36,7 @@
 import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.popup.PopupContainerWithArrow;
+import com.android.launcher3.shortcuts.DeepShortcutManager;
 import com.android.launcher3.util.Thunk;
 
 import java.util.ArrayList;
@@ -103,8 +104,7 @@
 
         // If the request came from keyboard, do not add custom shortcuts as that is already
         // exposed as a direct shortcut
-        if (!fromKeyboard && host instanceof BubbleTextView
-                && ((BubbleTextView) host).hasDeepShortcuts()) {
+        if (!fromKeyboard && DeepShortcutManager.supportsShortcuts(item)) {
             info.addAction(mActions.get(DEEP_SHORTCUTS));
         }
 
diff --git a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
index 2ad0edb..8161219 100644
--- a/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/ShortcutMenuAccessibilityDelegate.java
@@ -18,6 +18,7 @@
 
 import android.view.View;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.ItemInfo;
@@ -25,6 +26,7 @@
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.R;
 import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.notification.NotificationMainView;
 import com.android.launcher3.shortcuts.DeepShortcutView;
 
 import java.util.ArrayList;
@@ -35,14 +37,23 @@
  */
 public class ShortcutMenuAccessibilityDelegate extends LauncherAccessibilityDelegate {
 
+    private static final int DISMISS_NOTIFICATION = R.id.action_dismiss_notification;
+
     public ShortcutMenuAccessibilityDelegate(Launcher launcher) {
         super(launcher);
+        mActions.put(DISMISS_NOTIFICATION, new AccessibilityAction(DISMISS_NOTIFICATION,
+                launcher.getText(R.string.action_dismiss_notification)));
     }
 
     @Override
     public void addSupportedActions(View host, AccessibilityNodeInfo info, boolean fromKeyboard) {
         if ((host.getParent() instanceof DeepShortcutView)) {
             info.addAction(mActions.get(ADD_TO_WORKSPACE));
+        } else if (host instanceof NotificationMainView) {
+            NotificationMainView notificationView = (NotificationMainView) host;
+            if (notificationView.canChildBeDismissed(notificationView)) {
+                info.addAction(mActions.get(DISMISS_NOTIFICATION));
+            }
         }
     }
 
@@ -73,6 +84,14 @@
                 onComplete.run();
             }
             return true;
+        } else if (action == DISMISS_NOTIFICATION) {
+            if (!(host instanceof NotificationMainView)) {
+                return false;
+            }
+            NotificationMainView notificationView = (NotificationMainView) host;
+            notificationView.onChildDismissed(notificationView);
+            announceConfirmation(R.string.notification_dismissed);
+            return true;
         }
         return false;
     }
diff --git a/src/com/android/launcher3/badge/BadgeRenderer.java b/src/com/android/launcher3/badge/BadgeRenderer.java
index ba1977a..adde4a2 100644
--- a/src/com/android/launcher3/badge/BadgeRenderer.java
+++ b/src/com/android/launcher3/badge/BadgeRenderer.java
@@ -63,6 +63,7 @@
     private final Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG
             | Paint.FILTER_BITMAP_FLAG);
     private final SparseArray<Bitmap> mBackgroundsWithShadow;
+    private final IconPalette mIconPalette;
 
     public BadgeRenderer(Context context, int iconSizePx) {
         mContext = context;
@@ -82,24 +83,25 @@
         mTextHeight = tempTextHeight.height();
 
         mBackgroundsWithShadow = new SparseArray<>(3);
+
+        mIconPalette = IconPalette.fromDominantColor(context.getColor(R.color.badge_color));
     }
 
     /**
      * Draw a circle in the top right corner of the given bounds, and draw
      * {@link BadgeInfo#getNotificationCount()} on top of the circle.
-     * @param palette The colors (based on the icon) to use for the badge.
      * @param badgeInfo Contains data to draw on the badge. Could be null if we are animating out.
      * @param iconBounds The bounds of the icon being badged.
      * @param badgeScale The progress of the animation, from 0 to 1.
      * @param spaceForOffset How much space is available to offset the badge up and to the right.
      */
-    public void draw(Canvas canvas, IconPalette palette, @Nullable BadgeInfo badgeInfo,
+    public void draw(Canvas canvas, @Nullable BadgeInfo badgeInfo,
             Rect iconBounds, float badgeScale, Point spaceForOffset) {
-        mTextPaint.setColor(palette.textColor);
+        mTextPaint.setColor(mIconPalette.textColor);
         IconDrawer iconDrawer = badgeInfo != null && badgeInfo.isIconLarge()
                 ? mLargeIconDrawer : mSmallIconDrawer;
         Shader icon = badgeInfo == null ? null : badgeInfo.getNotificationIconForBadge(
-                mContext, palette.backgroundColor, mSize, iconDrawer.mPadding);
+                mContext, mIconPalette.backgroundColor, mSize, iconDrawer.mPadding);
         String notificationCount = badgeInfo == null ? "0"
                 : String.valueOf(badgeInfo.getNotificationCount());
         int numChars = notificationCount.length();
@@ -125,7 +127,7 @@
         canvas.translate(badgeCenterX + offsetX, badgeCenterY - offsetY);
         canvas.scale(badgeScale, badgeScale);
         // Prepare the background and shadow and possible stacking effect.
-        mBackgroundPaint.setColorFilter(palette.backgroundColorMatrixFilter);
+        mBackgroundPaint.setColorFilter(mIconPalette.backgroundColorMatrixFilter);
         int backgroundWithShadowSize = backgroundWithShadow.getHeight(); // Same as width.
         boolean shouldStack = !isDot && badgeInfo != null
                 && badgeInfo.getNotificationKeys().size() > 1;
@@ -147,7 +149,7 @@
                     -backgroundWithShadowSize / 2, mBackgroundPaint);
             iconDrawer.drawIcon(icon, canvas);
         } else if (isDot) {
-            mBackgroundPaint.setColorFilter(palette.saturatedBackgroundColorMatrixFilter);
+            mBackgroundPaint.setColorFilter(mIconPalette.saturatedBackgroundColorMatrixFilter);
             canvas.drawBitmap(backgroundWithShadow, -backgroundWithShadowSize / 2,
                     -backgroundWithShadowSize / 2, mBackgroundPaint);
         }
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 6e3db0b..4548792 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -75,7 +75,6 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.dragndrop.DragView;
-import com.android.launcher3.graphics.IconPalette;
 import com.android.launcher3.util.Thunk;
 
 import java.util.ArrayList;
@@ -933,7 +932,7 @@
             // If we are animating to the accepting state, animate the badge out.
             float badgeScale = Math.max(0, mBadgeScale - mBackground.getScaleProgress());
             mTempSpaceForBadgeOffset.set(getWidth() - mTempBounds.right, mTempBounds.top);
-            mBadgeRenderer.draw(canvas, IconPalette.FOLDER_ICON_PALETTE, mBadgeInfo, mTempBounds,
+            mBadgeRenderer.draw(canvas, mBadgeInfo, mTempBounds,
                     badgeScale, mTempSpaceForBadgeOffset);
         }
     }
diff --git a/src/com/android/launcher3/graphics/IconPalette.java b/src/com/android/launcher3/graphics/IconPalette.java
index 0182e53..60ca7b2 100644
--- a/src/com/android/launcher3/graphics/IconPalette.java
+++ b/src/com/android/launcher3/graphics/IconPalette.java
@@ -49,7 +49,7 @@
 
     private IconPalette(int color) {
         dominantColor = color;
-        backgroundColor = getMutedColor(dominantColor);
+        backgroundColor = dominantColor;
         ColorMatrix backgroundColorMatrix = new ColorMatrix();
         Themes.setColorScaleOnMatrix(backgroundColor, backgroundColorMatrix);
         backgroundColorMatrixFilter = new ColorMatrixColorFilter(backgroundColorMatrix);
@@ -176,10 +176,6 @@
         return ColorUtils.LABToColor(low, a, b);
     }
 
-    private static int getMutedColor(int color) {
-        return getMutedColor(color, 0.87f);
-    }
-
     private static int getMutedColor(int color, float whiteScrimAlpha) {
         int whiteScrim = ColorUtils.setAlphaComponent(Color.WHITE, (int) (255 * whiteScrimAlpha));
         return ColorUtils.compositeColors(whiteScrim, color);
diff --git a/src/com/android/launcher3/notification/NotificationFooterLayout.java b/src/com/android/launcher3/notification/NotificationFooterLayout.java
index 1eef743..051c033 100644
--- a/src/com/android/launcher3/notification/NotificationFooterLayout.java
+++ b/src/com/android/launcher3/notification/NotificationFooterLayout.java
@@ -141,6 +141,7 @@
         icon.setBackground(info.getIconForBackground(getContext(), mBackgroundColor));
         icon.setOnClickListener(info);
         icon.setTag(info);
+        icon.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
         mIconRow.addView(icon, 0, mIconLayoutParams);
         return icon;
     }
diff --git a/src/com/android/launcher3/notification/NotificationItemView.java b/src/com/android/launcher3/notification/NotificationItemView.java
index dd272b3..997def2 100644
--- a/src/com/android/launcher3/notification/NotificationItemView.java
+++ b/src/com/android/launcher3/notification/NotificationItemView.java
@@ -77,6 +77,10 @@
         mSwipeHelper.setDisableHardwareLayers(true);
     }
 
+    public NotificationMainView getMainView() {
+        return mMainView;
+    }
+
     public int getHeightMinusFooter() {
         int footerHeight = mFooter.getParent() == null ? 0 : mFooter.getHeight();
         return getHeight() - footerHeight;
diff --git a/src/com/android/launcher3/notification/NotificationMainView.java b/src/com/android/launcher3/notification/NotificationMainView.java
index d6e0272..0d6da77 100644
--- a/src/com/android/launcher3/notification/NotificationMainView.java
+++ b/src/com/android/launcher3/notification/NotificationMainView.java
@@ -122,7 +122,7 @@
 
     @Override
     public boolean canChildBeDismissed(View v) {
-        return mNotificationInfo.dismissable;
+        return mNotificationInfo != null && mNotificationInfo.dismissable;
     }
 
     @Override
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index d4ee3b8..ccead37 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -114,7 +114,6 @@
 
         mStartDragThreshold = getResources().getDimensionPixelSize(
                 R.dimen.deep_shortcuts_start_drag_threshold);
-        // TODO: make sure the delegate works for all items, not just shortcuts.
         mAccessibilityDelegate = new ShortcutMenuAccessibilityDelegate(mLauncher);
         mIsRtl = Utilities.isRtl(getResources());
     }
@@ -176,7 +175,7 @@
         // Add dummy views first, and populate with real info when ready.
         PopupPopulator.Item[] itemsToPopulate = PopupPopulator
                 .getItemsToPopulate(shortcutIds, notificationKeys, systemShortcuts);
-        addDummyViews(originalIcon, itemsToPopulate, notificationKeys.size() > 1);
+        addDummyViews(itemsToPopulate, notificationKeys.size() > 1);
 
         measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
         orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset);
@@ -187,7 +186,7 @@
             mNotificationItemView = null;
             mShortcutsItemView = null;
             itemsToPopulate = PopupPopulator.reverseItems(itemsToPopulate);
-            addDummyViews(originalIcon, itemsToPopulate, notificationKeys.size() > 1);
+            addDummyViews(itemsToPopulate, notificationKeys.size() > 1);
 
             measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
             orientAboutIcon(originalIcon, arrowHeight + arrowVerticalOffset);
@@ -204,6 +203,17 @@
             updateNotificationHeader();
         }
 
+        int numShortcuts = shortcutViews.size() + systemShortcutViews.size();
+        int numNotifications = notificationKeys.size();
+        if (numNotifications == 0) {
+            setContentDescription(getContext().getString(R.string.shortcuts_menu_description,
+                    numShortcuts, originalIcon.getContentDescription().toString()));
+        } else {
+            setContentDescription(getContext().getString(
+                    R.string.shortcuts_menu_with_notifications_description, numShortcuts,
+                    numNotifications, originalIcon.getContentDescription().toString()));
+        }
+
         // Add the arrow.
         final int arrowHorizontalOffset = resources.getDimensionPixelSize(isAlignedWithStart() ?
                 R.dimen.popup_arrow_horizontal_offset_start :
@@ -225,8 +235,8 @@
                 systemShortcuts, systemShortcutViews));
     }
 
-    private void addDummyViews(BubbleTextView originalIcon,
-            PopupPopulator.Item[] itemTypesToPopulate, boolean notificationFooterHasIcons) {
+    private void addDummyViews(PopupPopulator.Item[] itemTypesToPopulate,
+            boolean notificationFooterHasIcons) {
         final Resources res = getResources();
         final int spacing = res.getDimensionPixelSize(R.dimen.popup_items_spacing);
         final LayoutInflater inflater = mLauncher.getLayoutInflater();
@@ -243,12 +253,14 @@
                 int footerHeight = notificationFooterHasIcons ?
                         res.getDimensionPixelSize(R.dimen.notification_footer_height) : 0;
                 item.findViewById(R.id.footer).getLayoutParams().height = footerHeight;
+                mNotificationItemView.getMainView().setAccessibilityDelegate(mAccessibilityDelegate);
+            } else if (itemTypeToPopulate == PopupPopulator.Item.SHORTCUT) {
+                item.setAccessibilityDelegate(mAccessibilityDelegate);
             }
 
             boolean shouldAddBottomMargin = nextItemTypeToPopulate != null
                     && itemTypeToPopulate.isShortcut ^ nextItemTypeToPopulate.isShortcut;
 
-            item.setAccessibilityDelegate(mAccessibilityDelegate);
             if (itemTypeToPopulate.isShortcut) {
                 if (mShortcutsItemView == null) {
                     mShortcutsItemView = (ShortcutsItemView) inflater.inflate(
@@ -266,9 +278,6 @@
                 }
             }
         }
-        // TODO: update this, since not all items are shortcuts
-        setContentDescription(getContext().getString(R.string.shortcuts_menu_description,
-                numItems, originalIcon.getContentDescription().toString()));
     }
 
     protected PopupItemView getItemViewAt(int index) {