From 1cc100844cec75e827aa787f8ba9932f36d2d2e4 Mon Sep 17 00:00:00 2001 From: Mady Mellor Date: Mon, 5 Feb 2024 09:30:03 -0800 Subject: Add a bubble option to launcher long press menus - Add a launcher "system shortcut" to bubble deep shortcuts or apps - For shortcuts, save the shortcut info to use to produce the bubble - Add an interface so that the system shortcut can call through to sysui proxy Flag: com.android.wm.shell.enable_bubble_anything Test: manual - enable the flag and try to bubble a shortcut via the longpress menu on launcher - try bubbling an app on launcher - try bubbling an app from the taskbar Bug: 342245211 Change-Id: I1ef49e1628ba0be9cea05073ecd9cd66bf67f88f --- .../launcher3/taskbar/BaseTaskbarContext.java | 19 ++++++- .../launcher3/taskbar/TaskbarPopupController.java | 15 ++++-- .../launcher3/uioverrides/QuickstepLauncher.java | 20 ++++++- .../src/com/android/quickstep/SystemUiProxy.java | 31 ++++++++++- res/drawable/ic_bubble_button.xml | 25 +++++++++ res/values/strings.xml | 3 +- .../launcher3/model/data/WorkspaceItemInfo.java | 11 ++++ .../android/launcher3/popup/SystemShortcut.java | 63 ++++++++++++++++++++++ 8 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 res/drawable/ic_bubble_button.xml diff --git a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java index c201236586..a833ccf9c4 100644 --- a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java @@ -16,19 +16,24 @@ package com.android.launcher3.taskbar; import android.content.Context; +import android.content.Intent; +import android.content.pm.ShortcutInfo; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; +import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.util.Themes; import com.android.launcher3.views.ActivityContext; +import com.android.quickstep.SystemUiProxy; import java.util.ArrayList; import java.util.List; // TODO(b/218912746): Share more behavior to avoid all apps context depending directly on taskbar. /** Base for common behavior between taskbar window contexts. */ -public abstract class BaseTaskbarContext extends ContextThemeWrapper implements ActivityContext { +public abstract class BaseTaskbarContext extends ContextThemeWrapper implements ActivityContext, + SystemShortcut.BubbleActivityStarter { protected final LayoutInflater mLayoutInflater; private final List mDPChangeListeners = new ArrayList<>(); @@ -48,6 +53,18 @@ public abstract class BaseTaskbarContext extends ContextThemeWrapper implements return mDPChangeListeners; } + @Override + public void showShortcutBubble(ShortcutInfo info) { + if (info == null) return; + SystemUiProxy.INSTANCE.get(this).showShortcutBubble(info); + } + + @Override + public void showAppBubble(Intent intent) { + if (intent == null || intent.getPackage() == null) return; + SystemUiProxy.INSTANCE.get(this).showAppBubble(intent); + } + /** Callback invoked when a drag is initiated within this context. */ public abstract void onDragStart(); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java index b69759039a..e80ad7a8a1 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java @@ -53,6 +53,7 @@ import com.android.quickstep.SystemUiProxy; import com.android.quickstep.util.LogUtils; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Objects; @@ -69,6 +70,9 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba private static final SystemShortcut.Factory APP_INFO = SystemShortcut.AppInfo::new; + private static final SystemShortcut.Factory + BUBBLE = SystemShortcut.BubbleShortcut::new; + private final TaskbarActivityContext mContext; private final PopupDataProvider mPopupDataProvider; @@ -182,10 +186,13 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba // Create a Stream of all applicable system shortcuts private Stream getSystemShortcuts() { // append split options to APP_INFO shortcut, the order here will reflect in the popup - return Stream.concat( - Stream.of(APP_INFO), - mControllers.uiController.getSplitMenuOptions() - ); + ArrayList shortcuts = new ArrayList<>(); + shortcuts.add(APP_INFO); + shortcuts.addAll(mControllers.uiController.getSplitMenuOptions().toList()); + if (com.android.wm.shell.Flags.enableBubbleAnything()) { + shortcuts.add(BUBBLE); + } + return shortcuts.stream(); } @Override diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index b2cc369376..5a288b0336 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -45,6 +45,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID; import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition; import static com.android.launcher3.popup.SystemShortcut.APP_INFO; +import static com.android.launcher3.popup.SystemShortcut.BUBBLE_SHORTCUT; import static com.android.launcher3.popup.SystemShortcut.DONT_SUGGEST_APP; import static com.android.launcher3.popup.SystemShortcut.INSTALL; import static com.android.launcher3.popup.SystemShortcut.PRIVATE_PROFILE_INSTALL; @@ -75,6 +76,7 @@ import android.app.ActivityOptions; import android.content.Context; import android.content.Intent; import android.content.IntentSender; +import android.content.pm.ShortcutInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.graphics.RectF; @@ -215,7 +217,8 @@ import java.util.function.BiConsumer; import java.util.function.Predicate; import java.util.stream.Stream; -public class QuickstepLauncher extends Launcher implements RecentsViewContainer { +public class QuickstepLauncher extends Launcher implements RecentsViewContainer, + SystemShortcut.BubbleActivityStarter { private static final boolean TRACE_LAYOUTS = SystemProperties.getBoolean("persist.debug.trace_layouts", false); private static final String TRACE_RELAYOUT_CLASS = @@ -466,6 +469,9 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer if (Flags.enablePrivateSpace()) { shortcuts.add(UNINSTALL_APP); } + if (com.android.wm.shell.Flags.enableBubbleAnything()) { + shortcuts.add(BUBBLE_SHORTCUT); + } return shortcuts.stream(); } @@ -1436,6 +1442,18 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer return true; } + @Override + public void showShortcutBubble(ShortcutInfo info) { + if (info == null) return; + SystemUiProxy.INSTANCE.get(this).showShortcutBubble(info); + } + + @Override + public void showAppBubble(Intent intent) { + if (intent == null || intent.getPackage() == null) return; + SystemUiProxy.INSTANCE.get(this).showAppBubble(intent); + } + private static final class LauncherTaskViewController extends TaskViewTouchController { diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 0c2f29b8db..59e9f054c8 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -47,7 +47,6 @@ import android.view.IRecentsAnimationController; import android.view.IRecentsAnimationRunner; import android.view.IRemoteAnimationRunner; import android.view.MotionEvent; -import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; import android.window.IOnBackInvokedCallback; @@ -894,6 +893,36 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable { } } + /** + * Tells SysUI to show a shortcut bubble. + * + * @param info the shortcut info used to create or identify the bubble. + */ + public void showShortcutBubble(ShortcutInfo info) { + try { + if (mBubbles != null) { + mBubbles.showShortcutBubble(info); + } + } catch (RemoteException e) { + Log.w(TAG, "Failed call show bubble for shortcut"); + } + } + + /** + * Tells SysUI to show a bubble of an app. + * + * @param intent the intent used to create the bubble. + */ + public void showAppBubble(Intent intent) { + try { + if (mBubbles != null) { + mBubbles.showAppBubble(intent); + } + } catch (RemoteException e) { + Log.w(TAG, "Failed call show bubble for app"); + } + } + // // Splitscreen // diff --git a/res/drawable/ic_bubble_button.xml b/res/drawable/ic_bubble_button.xml new file mode 100644 index 0000000000..1ed212e09a --- /dev/null +++ b/res/drawable/ic_bubble_button.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 3b458c2cff..fd724a5553 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -215,7 +215,8 @@ Don\'t suggest app Pin Prediction - + + Bubble diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java index 40e3813fe3..f31bf1e5fe 100644 --- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java +++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java @@ -25,6 +25,7 @@ import android.text.TextUtils; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.android.launcher3.Flags; import com.android.launcher3.LauncherSettings; @@ -97,6 +98,8 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon { public int options; + @Nullable + private ShortcutInfo mShortcutInfo = null; public WorkspaceItemInfo() { itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; @@ -175,6 +178,9 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon { public void updateFromDeepShortcutInfo(@NonNull final ShortcutInfo shortcutInfo, @NonNull final Context context) { + if (com.android.wm.shell.Flags.enableBubbleAnything()) { + mShortcutInfo = shortcutInfo; + } // {@link ShortcutInfo#getActivity} can change during an update. Recreate the intent intent = ShortcutKey.makeIntent(shortcutInfo); title = shortcutInfo.getShortLabel(); @@ -204,6 +210,11 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon { : Arrays.stream(persons).map(Person::getKey).sorted().toArray(String[]::new); } + @Nullable + public ShortcutInfo getDeepShortcutInfo() { + return mShortcutInfo; + } + /** * {@code true} if the shortcut is disabled due to its app being a lower version. */ diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java index f7e116819a..0c90eb904a 100644 --- a/src/com/android/launcher3/popup/SystemShortcut.java +++ b/src/com/android/launcher3/popup/SystemShortcut.java @@ -11,9 +11,11 @@ import android.app.ActivityOptions; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.ShortcutInfo; import android.graphics.Rect; import android.os.Process; import android.os.UserHandle; +import android.util.Log; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.ImageView; @@ -25,6 +27,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.AbstractFloatingViewHelper; import com.android.launcher3.Flags; +import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; import com.android.launcher3.SecondaryDropTarget; import com.android.launcher3.Utilities; @@ -53,6 +56,7 @@ import java.util.Arrays; */ public abstract class SystemShortcut extends ItemInfo implements View.OnClickListener { + private static final String TAG = "SystemShortcut"; private final int mIconResId; protected final int mLabelResId; @@ -383,4 +387,63 @@ public abstract class SystemShortcut extends ItemInfo mAbstractFloatingViewHelper.closeOpenViews(mTarget, true, AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE); } + + public static final Factory BUBBLE_SHORTCUT = + (activity, itemInfo, originalView) -> { + if ((itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) + && (itemInfo.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) + && !(itemInfo instanceof WorkspaceItemInfo)) { + return null; + } + return new BubbleShortcut(activity, itemInfo, originalView); + }; + + public interface BubbleActivityStarter { + /** Tell SysUI to show the provided shortcut in a bubble. */ + void showShortcutBubble(ShortcutInfo info); + + /** Tell SysUI to show the provided intent in a bubble. */ + void showAppBubble(Intent intent); + } + + public static class BubbleShortcut extends SystemShortcut { + + private BubbleActivityStarter mStarter; + + public BubbleShortcut(T target, ItemInfo itemInfo, View originalView) { + super(R.drawable.ic_bubble_button, R.string.bubble, target, + itemInfo, originalView); + if (target instanceof BubbleActivityStarter) { + mStarter = (BubbleActivityStarter) target; + } + } + + @Override + public void onClick(View view) { + dismissTaskMenuView(); + if (mStarter == null) { + Log.w(TAG, "starter null!"); + return; + } + // TODO: handle GroupTask (single) items so that recent items in taskbar work + if (mItemInfo instanceof WorkspaceItemInfo) { + WorkspaceItemInfo workspaceItemInfo = (WorkspaceItemInfo) mItemInfo; + ShortcutInfo shortcutInfo = workspaceItemInfo.getDeepShortcutInfo(); + if (shortcutInfo != null) { + mStarter.showShortcutBubble(shortcutInfo); + return; + } + } + // If we're here check for an intent + Intent intent = mItemInfo.getIntent(); + if (intent != null) { + if (intent.getPackage() == null) { + intent.setPackage(mItemInfo.getTargetPackage()); + } + mStarter.showAppBubble(intent); + } else { + Log.w(TAG, "unable to bubble, no intent: " + mItemInfo); + } + } + } } -- cgit v1.2.3-59-g8ed1b