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.util.Pair;
26 import android.view.KeyEvent;
27 import android.view.View;
28 
29 import com.android.internal.logging.InstanceId;
30 import com.android.launcher3.BubbleTextView;
31 import com.android.launcher3.LauncherSettings;
32 import com.android.launcher3.R;
33 import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
34 import com.android.launcher3.logging.StatsLogManager;
35 import com.android.launcher3.model.data.ItemInfo;
36 import com.android.launcher3.model.data.ItemInfoWithIcon;
37 import com.android.launcher3.model.data.WorkspaceItemInfo;
38 import com.android.launcher3.util.ShortcutUtil;
39 import com.android.quickstep.SystemUiProxy;
40 import com.android.quickstep.util.LogUtils;
41 
42 import java.util.List;
43 
44 /**
45  * Accessibility delegate for the Taskbar. This provides an accessible interface for taskbar
46  * features.
47  */
48 public class TaskbarShortcutMenuAccessibilityDelegate
49         extends BaseAccessibilityDelegate<TaskbarActivityContext> {
50 
51     public static final int MOVE_TO_TOP_OR_LEFT = R.id.action_move_to_top_or_left;
52     public static final int MOVE_TO_BOTTOM_OR_RIGHT = R.id.action_move_to_bottom_or_right;
53 
54     private final LauncherApps mLauncherApps;
55     private final StatsLogManager mStatsLogManager;
56 
TaskbarShortcutMenuAccessibilityDelegate(TaskbarActivityContext context)57     public TaskbarShortcutMenuAccessibilityDelegate(TaskbarActivityContext context) {
58         super(context);
59         mLauncherApps = context.getSystemService(LauncherApps.class);
60         mStatsLogManager = context.getStatsLogManager();
61 
62         mActions.put(DEEP_SHORTCUTS, new LauncherAction(DEEP_SHORTCUTS,
63                 R.string.action_deep_shortcut, KeyEvent.KEYCODE_S));
64         mActions.put(MOVE_TO_TOP_OR_LEFT, new LauncherAction(
65                 MOVE_TO_TOP_OR_LEFT, R.string.move_drop_target_top_or_left, KeyEvent.KEYCODE_L));
66         mActions.put(MOVE_TO_BOTTOM_OR_RIGHT, new LauncherAction(
67                 MOVE_TO_BOTTOM_OR_RIGHT,
68                 R.string.move_drop_target_bottom_or_right,
69                 KeyEvent.KEYCODE_R));
70     }
71 
72     @Override
getSupportedActions(View host, ItemInfo item, List<LauncherAction> out)73     protected void getSupportedActions(View host, ItemInfo item, List<LauncherAction> out) {
74         if (ShortcutUtil.supportsShortcuts(item)) {
75             out.add(mActions.get(DEEP_SHORTCUTS));
76         }
77         out.add(mActions.get(MOVE_TO_TOP_OR_LEFT));
78         out.add(mActions.get(MOVE_TO_BOTTOM_OR_RIGHT));
79     }
80 
81     @Override
performAction(View host, ItemInfo item, int action, boolean fromKeyboard)82     protected boolean performAction(View host, ItemInfo item, int action, boolean fromKeyboard) {
83         if (item instanceof ItemInfoWithIcon
84                 && (action == MOVE_TO_TOP_OR_LEFT || action == MOVE_TO_BOTTOM_OR_RIGHT)) {
85             ItemInfoWithIcon info = (ItemInfoWithIcon) item;
86             int side = action == MOVE_TO_TOP_OR_LEFT
87                     ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT;
88 
89             Pair<InstanceId, com.android.launcher3.logging.InstanceId> instanceIds =
90                     LogUtils.getShellShareableInstanceId();
91             mStatsLogManager.logger()
92                     .withItemInfo(item)
93                     .withInstanceId(instanceIds.second)
94                     .log(getLogEventForPosition(side));
95 
96             if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
97                     && item instanceof WorkspaceItemInfo) {
98                 SystemUiProxy.INSTANCE.get(mContext).startShortcut(
99                         info.getIntent().getPackage(),
100                         ((WorkspaceItemInfo) info).getDeepShortcutId(),
101                         side,
102                         /* bundleOpts= */ null,
103                         info.user,
104                         instanceIds.first);
105             } else {
106                 SystemUiProxy.INSTANCE.get(mContext).startIntent(
107                         mLauncherApps.getMainActivityLaunchIntent(
108                                 item.getIntent().getComponent(),
109                                 /* startActivityOptions= */null,
110                                 item.user),
111                         item.user.getIdentifier(), new Intent(), side, null,
112                         instanceIds.first);
113             }
114             return true;
115         } else if (action == DEEP_SHORTCUTS) {
116             mContext.showPopupMenuForIcon((BubbleTextView) host);
117 
118             return true;
119         }
120         return false;
121     }
122 
123     @Override
beginAccessibleDrag(View item, ItemInfo info, boolean fromKeyboard)124     protected boolean beginAccessibleDrag(View item, ItemInfo info, boolean fromKeyboard) {
125         return false;
126     }
127 }
128