1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.launcher3.taskbar; 17 18 import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DEEP_SHORTCUTS; 19 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; 20 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT; 21 import static com.android.launcher3.util.SplitConfigurationOptions.getLogEventForPosition; 22 23 import android.content.Intent; 24 import android.content.pm.LauncherApps; 25 import android.content.pm.ShortcutInfo; 26 import android.util.Pair; 27 import android.view.KeyEvent; 28 import android.view.View; 29 30 import com.android.internal.logging.InstanceId; 31 import com.android.launcher3.BubbleTextView; 32 import com.android.launcher3.LauncherSettings; 33 import com.android.launcher3.R; 34 import com.android.launcher3.accessibility.BaseAccessibilityDelegate; 35 import com.android.launcher3.logging.StatsLogManager; 36 import com.android.launcher3.model.data.ItemInfo; 37 import com.android.launcher3.model.data.ItemInfoWithIcon; 38 import com.android.launcher3.model.data.WorkspaceItemInfo; 39 import com.android.launcher3.util.ShortcutUtil; 40 import com.android.quickstep.SystemUiProxy; 41 import com.android.quickstep.util.LogUtils; 42 import com.android.wm.shell.shared.bubbles.BubbleAnythingFlagHelper; 43 44 import java.util.List; 45 46 /** 47 * Accessibility delegate for the Taskbar. This provides an accessible interface for taskbar 48 * features. 49 */ 50 public class TaskbarShortcutMenuAccessibilityDelegate 51 extends BaseAccessibilityDelegate<TaskbarActivityContext> { 52 53 public static final int MOVE_TO_TOP_OR_LEFT = R.id.action_move_to_top_or_left; 54 public static final int MOVE_TO_BOTTOM_OR_RIGHT = R.id.action_move_to_bottom_or_right; 55 public static final int CREATE_APPLICATION_BUBBLE = R.id.action_create_application_bubble; 56 57 private final LauncherApps mLauncherApps; 58 private final StatsLogManager mStatsLogManager; 59 TaskbarShortcutMenuAccessibilityDelegate(TaskbarActivityContext context)60 public TaskbarShortcutMenuAccessibilityDelegate(TaskbarActivityContext context) { 61 super(context); 62 mLauncherApps = context.getSystemService(LauncherApps.class); 63 mStatsLogManager = context.getStatsLogManager(); 64 65 mActions.put(DEEP_SHORTCUTS, new LauncherAction(DEEP_SHORTCUTS, 66 R.string.action_deep_shortcut, KeyEvent.KEYCODE_S)); 67 mActions.put(MOVE_TO_TOP_OR_LEFT, new LauncherAction( 68 MOVE_TO_TOP_OR_LEFT, R.string.move_drop_target_top_or_left, KeyEvent.KEYCODE_L)); 69 mActions.put(MOVE_TO_BOTTOM_OR_RIGHT, new LauncherAction( 70 MOVE_TO_BOTTOM_OR_RIGHT, 71 R.string.move_drop_target_bottom_or_right, 72 KeyEvent.KEYCODE_R)); 73 mActions.put(CREATE_APPLICATION_BUBBLE, new LauncherAction( 74 CREATE_APPLICATION_BUBBLE, R.string.open_app_as_a_bubble, 75 KeyEvent.KEYCODE_L)); 76 } 77 78 @Override getSupportedActions(View host, ItemInfo item, List<LauncherAction> out)79 protected void getSupportedActions(View host, ItemInfo item, List<LauncherAction> out) { 80 if (ShortcutUtil.supportsShortcuts(item)) { 81 out.add(mActions.get(DEEP_SHORTCUTS)); 82 } 83 out.add(mActions.get(MOVE_TO_TOP_OR_LEFT)); 84 out.add(mActions.get(MOVE_TO_BOTTOM_OR_RIGHT)); 85 if (BubbleAnythingFlagHelper.enableCreateAnyBubble()) { 86 out.add(mActions.get(CREATE_APPLICATION_BUBBLE)); 87 } 88 } 89 90 @Override performAction(View host, ItemInfo item, int action, boolean fromKeyboard)91 protected boolean performAction(View host, ItemInfo item, int action, boolean fromKeyboard) { 92 if (action == DEEP_SHORTCUTS) { 93 mContext.showPopupMenuForIcon((BubbleTextView) host); 94 return true; 95 } else if (action == CREATE_APPLICATION_BUBBLE) { 96 if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT 97 && item instanceof WorkspaceItemInfo) { 98 ShortcutInfo shortcutInfo = ((WorkspaceItemInfo) item).getDeepShortcutInfo(); 99 SystemUiProxy.INSTANCE.get(mContext).showShortcutBubble(shortcutInfo); 100 return true; 101 } else if (item.getIntent() != null && item.getIntent().getPackage() != null) { 102 SystemUiProxy.INSTANCE.get(mContext).showAppBubble(item.getIntent(), item.user); 103 return true; 104 } 105 } else if (item instanceof ItemInfoWithIcon 106 && (action == MOVE_TO_TOP_OR_LEFT || action == MOVE_TO_BOTTOM_OR_RIGHT)) { 107 ItemInfoWithIcon info = (ItemInfoWithIcon) item; 108 int side = action == MOVE_TO_TOP_OR_LEFT 109 ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT; 110 111 Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds = 112 LogUtils.getShellShareableInstanceId(); 113 mStatsLogManager.logger() 114 .withItemInfo(item) 115 .withInstanceId(instanceIds.second) 116 .log(getLogEventForPosition(side)); 117 118 if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT 119 && item instanceof WorkspaceItemInfo) { 120 SystemUiProxy.INSTANCE.get(mContext).startShortcut( 121 info.getIntent().getPackage(), 122 ((WorkspaceItemInfo) info).getDeepShortcutId(), 123 side, 124 /* bundleOpts= */ null, 125 info.user, 126 instanceIds.first); 127 } else { 128 SystemUiProxy.INSTANCE.get(mContext).startIntent( 129 mLauncherApps.getMainActivityLaunchIntent( 130 item.getIntent().getComponent(), 131 /* startActivityOptions= */null, 132 item.user), 133 item.user.getIdentifier(), new Intent(), side, null, 134 instanceIds.first); 135 } 136 return true; 137 } 138 return false; 139 } 140 141 @Override beginAccessibleDrag(View item, ItemInfo info, boolean fromKeyboard)142 protected boolean beginAccessibleDrag(View item, ItemInfo info, boolean fromKeyboard) { 143 return false; 144 } 145 } 146