• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.launcher3.popup;
2 
3 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP;
4 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP;
5 
6 import android.app.ActivityOptions;
7 import android.content.Context;
8 import android.content.Intent;
9 import android.graphics.Rect;
10 import android.view.View;
11 import android.view.accessibility.AccessibilityNodeInfo;
12 import android.widget.ImageView;
13 import android.widget.TextView;
14 
15 import androidx.annotation.Nullable;
16 
17 import com.android.launcher3.AbstractFloatingView;
18 import com.android.launcher3.BaseDraggingActivity;
19 import com.android.launcher3.Launcher;
20 import com.android.launcher3.R;
21 import com.android.launcher3.model.WidgetItem;
22 import com.android.launcher3.model.data.ItemInfo;
23 import com.android.launcher3.model.data.WorkspaceItemInfo;
24 import com.android.launcher3.util.InstantAppResolver;
25 import com.android.launcher3.util.PackageManagerHelper;
26 import com.android.launcher3.util.PackageUserKey;
27 import com.android.launcher3.widget.WidgetsBottomSheet;
28 
29 import java.util.List;
30 
31 /**
32  * Represents a system shortcut for a given app. The shortcut should have a label and icon, and an
33  * onClickListener that depends on the item that the shortcut services.
34  *
35  * Example system shortcuts, defined as inner classes, include Widgets and AppInfo.
36  * @param <T>
37  */
38 public abstract class SystemShortcut<T extends BaseDraggingActivity> extends ItemInfo
39         implements View.OnClickListener {
40 
41     private final int mIconResId;
42     private final int mLabelResId;
43     private final int mAccessibilityActionId;
44 
45     protected final T mTarget;
46     protected final ItemInfo mItemInfo;
47 
48     /**
49      * Indicates if it's invokable or not through some disabled UI
50      */
51     private boolean isEnabled = true;
52 
53     private boolean mHasFinishRecentsInAction = false;
54 
SystemShortcut(int iconResId, int labelResId, T target, ItemInfo itemInfo)55     public SystemShortcut(int iconResId, int labelResId, T target, ItemInfo itemInfo) {
56         mIconResId = iconResId;
57         mLabelResId = labelResId;
58         mAccessibilityActionId = labelResId;
59         mTarget = target;
60         mItemInfo = itemInfo;
61     }
62 
SystemShortcut(SystemShortcut<T> other)63     public SystemShortcut(SystemShortcut<T> other) {
64         mIconResId = other.mIconResId;
65         mLabelResId = other.mLabelResId;
66         mAccessibilityActionId = other.mAccessibilityActionId;
67         mTarget = other.mTarget;
68         mItemInfo = other.mItemInfo;
69     }
70 
71     /**
72      * Should be in the left group of icons in app's context menu header.
73      */
isLeftGroup()74     public boolean isLeftGroup() {
75         return false;
76     }
77 
setIconAndLabelFor(View iconView, TextView labelView)78     public void setIconAndLabelFor(View iconView, TextView labelView) {
79         iconView.setBackgroundResource(mIconResId);
80         labelView.setText(mLabelResId);
81     }
82 
setIconAndContentDescriptionFor(ImageView view)83     public void setIconAndContentDescriptionFor(ImageView view) {
84         view.setImageResource(mIconResId);
85         view.setContentDescription(view.getContext().getText(mLabelResId));
86     }
87 
createAccessibilityAction(Context context)88     public AccessibilityNodeInfo.AccessibilityAction createAccessibilityAction(Context context) {
89         return new AccessibilityNodeInfo.AccessibilityAction(
90                 mAccessibilityActionId, context.getText(mLabelResId));
91     }
92 
setEnabled(boolean enabled)93     public void setEnabled(boolean enabled) {
94         isEnabled = enabled;
95     }
96 
isEnabled()97     public boolean isEnabled() {
98         return isEnabled;
99     }
100 
hasHandlerForAction(int action)101     public boolean hasHandlerForAction(int action) {
102         return mAccessibilityActionId == action;
103     }
104 
setHasFinishRecentsInAction(boolean hasFinishRecentsInAction)105     public void setHasFinishRecentsInAction(boolean hasFinishRecentsInAction) {
106         mHasFinishRecentsInAction = hasFinishRecentsInAction;
107     }
108 
hasFinishRecentsInAction()109     public boolean hasFinishRecentsInAction() {
110         return mHasFinishRecentsInAction;
111     }
112 
113     public interface Factory<T extends BaseDraggingActivity> {
114 
getShortcut(T activity, ItemInfo itemInfo)115         @Nullable SystemShortcut<T> getShortcut(T activity, ItemInfo itemInfo);
116     }
117 
118     public static final Factory<Launcher> WIDGETS = (launcher, itemInfo) -> {
119         if (itemInfo.getTargetComponent() == null) return null;
120         final List<WidgetItem> widgets =
121                 launcher.getPopupDataProvider().getWidgetsForPackageUser(new PackageUserKey(
122                         itemInfo.getTargetComponent().getPackageName(), itemInfo.user));
123         if (widgets.isEmpty()) {
124             return null;
125         }
126         return new Widgets(launcher, itemInfo);
127     };
128 
129     public static class Widgets extends SystemShortcut<Launcher> {
Widgets(Launcher target, ItemInfo itemInfo)130         public Widgets(Launcher target, ItemInfo itemInfo) {
131             super(R.drawable.ic_widget, R.string.widget_button_text, target, itemInfo);
132         }
133 
134         @Override
onClick(View view)135         public void onClick(View view) {
136             AbstractFloatingView.closeAllOpenViews(mTarget);
137             WidgetsBottomSheet widgetsBottomSheet =
138                     (WidgetsBottomSheet) mTarget.getLayoutInflater().inflate(
139                             R.layout.widgets_bottom_sheet, mTarget.getDragLayer(), false);
140             widgetsBottomSheet.populateAndShow(mItemInfo);
141             mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo)
142                     .log(LAUNCHER_SYSTEM_SHORTCUT_WIDGETS_TAP);
143         }
144     }
145 
146     public static final Factory<BaseDraggingActivity> APP_INFO = AppInfo::new;
147 
148     public static class AppInfo extends SystemShortcut {
149 
AppInfo(BaseDraggingActivity target, ItemInfo itemInfo)150         public AppInfo(BaseDraggingActivity target, ItemInfo itemInfo) {
151             super(R.drawable.ic_info_no_shadow, R.string.app_info_drop_target_label, target,
152                     itemInfo);
153         }
154 
155         @Override
onClick(View view)156         public void onClick(View view) {
157             dismissTaskMenuView(mTarget);
158             Rect sourceBounds = mTarget.getViewBounds(view);
159             new PackageManagerHelper(mTarget).startDetailsActivityForInfo(
160                     mItemInfo, sourceBounds, ActivityOptions.makeBasic().toBundle());
161             mTarget.getStatsLogManager().logger().withItemInfo(mItemInfo)
162                     .log(LAUNCHER_SYSTEM_SHORTCUT_APP_INFO_TAP);
163         }
164     }
165 
166     public static final Factory<BaseDraggingActivity> INSTALL = (activity, itemInfo) -> {
167         boolean supportsWebUI = (itemInfo instanceof WorkspaceItemInfo)
168                 && ((WorkspaceItemInfo) itemInfo).hasStatusFlag(
169                         WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI);
170         boolean isInstantApp = false;
171         if (itemInfo instanceof com.android.launcher3.model.data.AppInfo) {
172             com.android.launcher3.model.data.AppInfo
173                     appInfo = (com.android.launcher3.model.data.AppInfo) itemInfo;
174             isInstantApp = InstantAppResolver.newInstance(activity).isInstantApp(appInfo);
175         }
176         boolean enabled = supportsWebUI || isInstantApp;
177         if (!enabled) {
178             return null;
179         }
180         return new Install(activity, itemInfo);
181     };
182 
183     public static class Install extends SystemShortcut {
184 
Install(BaseDraggingActivity target, ItemInfo itemInfo)185         public Install(BaseDraggingActivity target, ItemInfo itemInfo) {
186             super(R.drawable.ic_install_no_shadow, R.string.install_drop_target_label,
187                     target, itemInfo);
188         }
189 
190         @Override
onClick(View view)191         public void onClick(View view) {
192             Intent intent = new PackageManagerHelper(view.getContext()).getMarketIntent(
193                     mItemInfo.getTargetComponent().getPackageName());
194             mTarget.startActivitySafely(view, intent, mItemInfo);
195             AbstractFloatingView.closeAllOpenViews(mTarget);
196         }
197     }
198 
dismissTaskMenuView(BaseDraggingActivity activity)199     public static void dismissTaskMenuView(BaseDraggingActivity activity) {
200         AbstractFloatingView.closeOpenViews(activity, true,
201             AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);
202     }
203 }
204