show dot in deep shortcuts when notification contains exactly identical

set of person

Bug: 132336512
Change-Id: I975524e28168c10a186cdc24b188c161faf433cf
This commit is contained in:
Pinyao Ting 2019-07-26 12:28:38 -07:00
parent 1a4b815cd8
commit 49a3e699f9
13 changed files with 144 additions and 58 deletions

View File

@ -45,18 +45,6 @@ public class DeepShortcutManager {
private DeepShortcutManager() { }
public static boolean supportsShortcuts(ItemInfo info) {
return false;
}
public static boolean supportsDeepShortcuts(ItemInfo info) {
return false;
}
public static String getShortcutIdIfApplicable(ItemInfo info) {
return null;
}
/**
* Queries for the shortcuts with the package name and provided ids.
*

View File

@ -32,9 +32,11 @@ import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.Person;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ShortcutInfo;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.util.Base64;
@ -244,4 +246,9 @@ public class UiFactory extends RecentsUiFactory {
}
return new ScaleAndTranslation(1.1f, 0f, 0f);
}
public static Person[] getPersons(ShortcutInfo si) {
Person[] persons = si.getPersons();
return persons == null ? Utilities.EMPTY_PERSON_ARRAY : persons;
}
}

View File

@ -129,6 +129,7 @@ import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.PendingRequestArgs;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.ShortcutUtil;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
@ -2489,7 +2490,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
KeyEvent.KEYCODE_O, KeyEvent.META_CTRL_ON));
}
if (currentFocus.getTag() instanceof ItemInfo
&& DeepShortcutManager.supportsShortcuts((ItemInfo) currentFocus.getTag())) {
&& ShortcutUtil.supportsShortcuts((ItemInfo) currentFocus.getTag())) {
shortcutInfos.add(new KeyboardShortcutInfo(
getString(R.string.shortcuts_menu_with_notifications_description),
KeyEvent.KEYCODE_S, KeyEvent.META_CTRL_ON));

View File

@ -21,6 +21,7 @@ import static com.android.launcher3.ItemInfoWithIcon.FLAG_ICON_BADGED;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.ActivityManager;
import android.app.Person;
import android.app.WallpaperManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@ -97,6 +98,9 @@ public final class Utilities {
private static final Matrix sMatrix = new Matrix();
private static final Matrix sInverseMatrix = new Matrix();
public static final String[] EMPTY_STRING_ARRAY = new String[0];
public static final Person[] EMPTY_PERSON_ARRAY = new Person[0];
public static final boolean ATLEAST_Q = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q;
public static final boolean ATLEAST_P =

View File

@ -16,17 +16,23 @@
package com.android.launcher3;
import android.app.Person;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.util.ContentWriter;
import java.util.Arrays;
/**
* Represents a launchable icon on the workspaces and in folders.
*/
@ -82,11 +88,18 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon {
public int status;
/**
* A set of person's Id associated with the WorkspaceItemInfo, this is only used if the item
* represents a deep shortcut.
*/
@NonNull private String[] personKeys = Utilities.EMPTY_STRING_ARRAY;
/**
* The installation progress [0-100] of the package that this shortcut represents.
*/
private int mInstallProgress;
public WorkspaceItemInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
}
@ -98,6 +111,7 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon {
iconResource = info.iconResource;
status = info.status;
mInstallProgress = info.mInstallProgress;
personKeys = info.personKeys.clone();
}
/** TODO: Remove this. It's only called by ApplicationInfo.makeWorkspaceItem. */
@ -175,6 +189,10 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon {
runtimeStatusFlags |= FLAG_DISABLED_BY_PUBLISHER;
}
disabledMessage = shortcutInfo.getDisabledMessage();
Person[] persons = UiFactory.getPersons(shortcutInfo);
personKeys = persons.length == 0 ? Utilities.EMPTY_STRING_ARRAY
: Arrays.stream(persons).map(Person::getKey).sorted().toArray(String[]::new);
}
/** Returns the WorkspaceItemInfo id associated with the deep shortcut. */
@ -183,6 +201,11 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon {
getIntent().getStringExtra(ShortcutKey.EXTRA_SHORTCUT_ID) : null;
}
@NonNull
public String[] getPersonKeys() {
return personKeys;
}
@Override
public ComponentName getTargetComponent() {
ComponentName cn = super.getTargetComponent();

View File

@ -40,6 +40,7 @@ import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.ShortcutUtil;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
@ -115,7 +116,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
// If the request came from keyboard, do not add custom shortcuts as that is already
// exposed as a direct shortcut
if (!fromKeyboard && DeepShortcutManager.supportsShortcuts(item)) {
if (!fromKeyboard && ShortcutUtil.supportsShortcuts(item)) {
info.addAction(mActions.get(NotificationListener.getInstanceIfConnected() != null
? SHORTCUTS_AND_NOTIFICATIONS : DEEP_SHORTCUTS));
}

View File

@ -17,12 +17,18 @@
package com.android.launcher3.notification;
import android.app.Notification;
import android.app.Person;
import android.service.notification.StatusBarNotification;
import com.android.launcher3.Utilities;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/**
* The key data associated with the notification, used to determine what to include
@ -34,19 +40,25 @@ public class NotificationKeyData {
public final String notificationKey;
public final String shortcutId;
public int count;
@NonNull public final String[] personKeysFromNotification;
private NotificationKeyData(String notificationKey, String shortcutId, int count) {
private NotificationKeyData(String notificationKey, String shortcutId, int count,
String[] personKeysFromNotification) {
this.notificationKey = notificationKey;
this.shortcutId = shortcutId;
this.count = Math.max(1, count);
this.personKeysFromNotification = personKeysFromNotification;
}
public static NotificationKeyData fromNotification(StatusBarNotification sbn) {
Notification notif = sbn.getNotification();
return new NotificationKeyData(sbn.getKey(), notif.getShortcutId(), notif.number);
return new NotificationKeyData(sbn.getKey(), notif.getShortcutId(), notif.number,
extractPersonKeyOnly(notif.extras.getParcelableArrayList(
Notification.EXTRA_PEOPLE_LIST)));
}
public static List<String> extractKeysOnly(@NonNull List<NotificationKeyData> notificationKeys) {
public static List<String> extractKeysOnly(
@NonNull List<NotificationKeyData> notificationKeys) {
List<String> keysOnly = new ArrayList<>(notificationKeys.size());
for (NotificationKeyData notificationKeyData : notificationKeys) {
keysOnly.add(notificationKeyData.notificationKey);
@ -54,6 +66,13 @@ public class NotificationKeyData {
return keysOnly;
}
private static String[] extractPersonKeyOnly(@Nullable ArrayList<Person> people) {
if (people == null || people.isEmpty()) {
return Utilities.EMPTY_STRING_ARRAY;
}
return people.stream().map(Person::getKey).sorted().toArray(String[]::new);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof NotificationKeyData)) {

View File

@ -72,6 +72,7 @@ import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.ShortcutUtil;
import com.android.launcher3.views.BaseDragLayer;
import java.util.ArrayList;
@ -201,7 +202,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
return null;
}
ItemInfo itemInfo = (ItemInfo) icon.getTag();
if (!DeepShortcutManager.supportsShortcuts(itemInfo)) {
if (!ShortcutUtil.supportsShortcuts(itemInfo)) {
return null;
}

View File

@ -29,14 +29,17 @@ import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.ShortcutUtil;
import com.android.launcher3.widget.WidgetListRowEntry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
@ -158,7 +161,7 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan
}
public int getShortcutCountForItem(ItemInfo info) {
if (!DeepShortcutManager.supportsDeepShortcuts(info)) {
if (!ShortcutUtil.supportsDeepShortcuts(info)) {
return 0;
}
ComponentName component = info.getTargetComponent();
@ -171,7 +174,7 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan
}
public @Nullable DotInfo getDotInfoForItem(@NonNull ItemInfo info) {
if (!DeepShortcutManager.supportsShortcuts(info)) {
if (!ShortcutUtil.supportsShortcuts(info)) {
return null;
}
DotInfo dotInfo = mPackageUserToDotInfos.get(PackageUserKey.fromItemInfo(info));
@ -243,13 +246,20 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan
*/
public static @NonNull List<NotificationKeyData> getNotificationsForItem(
@NonNull ItemInfo info, @NonNull List<NotificationKeyData> notifications) {
String shortcutId = DeepShortcutManager.getShortcutIdIfApplicable(info);
String shortcutId = ShortcutUtil.getShortcutIdIfPinnedShortcut(info);
if (shortcutId == null) {
return notifications;
}
return notifications.stream().filter((NotificationKeyData notification) ->
shortcutId.equals(notification.shortcutId)
).collect(Collectors.toList());
String[] personKeys = ShortcutUtil.getPersonKeysIfPinnedShortcut(info);
return notifications.stream().filter((NotificationKeyData notification) -> {
if (notification.shortcutId != null) {
return notification.shortcutId.equals(shortcutId);
}
if (notification.personKeysFromNotification.length != 0) {
return Arrays.equals(notification.personKeysFromNotification, personKeys);
}
return false;
}).collect(Collectors.toList());
}
public interface PopupDataChangeListener {

View File

@ -38,7 +38,7 @@ public class PackageUserKey {
* @return Whether this PackageUserKey was successfully updated - it shouldn't be used if not.
*/
public boolean updateFromItemInfo(ItemInfo info) {
if (DeepShortcutManager.supportsShortcuts(info)) {
if (ShortcutUtil.supportsShortcuts(info)) {
update(info.getTargetComponent().getPackageName(), info.user);
return true;
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2019 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.launcher3.util;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.shortcuts.ShortcutKey;
public class ShortcutUtil {
public static boolean supportsShortcuts(ItemInfo info) {
return isActive(info) && (isApp(info) || isPinnedShortcut(info));
}
public static boolean supportsDeepShortcuts(ItemInfo info) {
return isActive(info) && isApp(info);
}
public static String getShortcutIdIfPinnedShortcut(ItemInfo info) {
return isActive(info) && isPinnedShortcut(info) ?
ShortcutKey.fromItemInfo(info).getId() : null;
}
public static String[] getPersonKeysIfPinnedShortcut(ItemInfo info) {
return isActive(info) && isPinnedShortcut(info) ?
((WorkspaceItemInfo) info).getPersonKeys() : Utilities.EMPTY_STRING_ARRAY;
}
private static boolean isActive(ItemInfo info) {
boolean isLoading = info instanceof WorkspaceItemInfo
&& ((WorkspaceItemInfo) info).hasPromiseIconUi();
return !isLoading && !info.isDisabled() && !FeatureFlags.GO_DISABLE_WIDGETS;
}
private static boolean isApp(ItemInfo info) {
return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
}
private static boolean isPinnedShortcut(ItemInfo info) {
return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
&& info.container != ItemInfo.NO_ID
&& info instanceof WorkspaceItemInfo;
}
}

View File

@ -27,10 +27,6 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.util.Log;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.WorkspaceItemInfo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -59,29 +55,6 @@ public class DeepShortcutManager {
mLauncherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
}
public static boolean supportsShortcuts(ItemInfo info) {
return isActive(info) && (isApp(info) || isPinnedShortcut(info));
}
public static boolean supportsDeepShortcuts(ItemInfo info) {
return isActive(info) && isApp(info);
}
public static String getShortcutIdIfApplicable(ItemInfo info) {
return isActive(info) && isPinnedShortcut(info) ?
ShortcutKey.fromItemInfo(info).getId() : null;
}
private static boolean isApp(ItemInfo info) {
return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
}
private static boolean isPinnedShortcut(ItemInfo info) {
return info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
&& info.container != ItemInfo.NO_ID
&& info instanceof WorkspaceItemInfo;
}
/**
* Queries for the shortcuts with the package name and provided ids.
*
@ -182,12 +155,6 @@ public class DeepShortcutManager {
return shortcutIds;
}
private static boolean isActive(ItemInfo info) {
boolean isLoading = info instanceof WorkspaceItemInfo
&& ((WorkspaceItemInfo) info).hasPromiseIconUi();
return !isLoading && !info.isDisabled();
}
/**
* Query the system server for all the shortcuts matching the given parameters.
* If packageName == null, we query for all shortcuts with the passed flags, regardless of app.

View File

@ -17,9 +17,11 @@
package com.android.launcher3.uioverrides;
import android.app.Activity;
import android.app.Person;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ShortcutInfo;
import android.os.Bundle;
import android.os.CancellationSignal;
@ -27,6 +29,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.Utilities;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.util.TouchController;
@ -95,4 +98,7 @@ public class UiFactory {
public static void clearSwipeSharedState(boolean finishAnimation) {}
public static Person[] getPersons(ShortcutInfo si) {
return Utilities.EMPTY_PERSON_ARRAY;
}
}