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