blob: 2d590033259fac85c6b07e45ef8db28c512b9c53 [file] [log] [blame]
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001/*
2 * Copyright (C) 2016 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 */
16package android.content.pm;
17
18import android.annotation.NonNull;
Makoto Onuki2d895c32016-12-02 15:48:40 -080019import android.annotation.Nullable;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060020import android.annotation.SystemService;
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070021import android.annotation.TestApi;
Mathew Inwood1c77a112018-08-14 14:06:26 +010022import android.annotation.UnsupportedAppUsage;
Makoto Onukid6e1f3b2016-06-14 11:17:59 -070023import android.annotation.UserIdInt;
Makoto Onukiac042502016-05-20 16:39:42 -070024import android.app.usage.UsageStatsManager;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080025import android.content.Context;
Makoto Onuki4a910962016-07-07 13:57:34 -070026import android.content.Intent;
Makoto Onuki2d895c32016-12-02 15:48:40 -080027import android.content.IntentSender;
Makoto Onuki9aeff8a2017-05-30 16:50:20 -070028import android.graphics.drawable.AdaptiveIconDrawable;
Mathew Inwood45d2c252018-09-14 12:35:36 +010029import android.os.Build;
Makoto Onuki16e83d02017-04-17 10:55:21 -070030import android.os.Build.VERSION_CODES;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080031import android.os.RemoteException;
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070032import android.os.ServiceManager;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080033
34import com.android.internal.annotations.VisibleForTesting;
35
36import java.util.List;
37
38/**
Laura Davisb93f8dd2018-08-07 09:53:52 -070039 * <p><code>ShortcutManager</code> executes operations on an app's set of <i>shortcuts</i>, which
40 * represent specific tasks and actions that users can perform within your app. This page lists
41 * components of the <code>ShortcutManager</code> class that you can use to create and manage
42 * sets of shortcuts.
Kevin Hufnagleb45780b2017-12-01 16:01:36 -080043 *
Laura Davisb93f8dd2018-08-07 09:53:52 -070044 * <p>To learn about methods that retrieve information about a single shortcut&mdash;including
45 * identifiers, type, and status&mdash;read the <code>
46 * <a href="/reference/android/content/pm/ShortcutInfo.html">ShortcutInfo</a></code> reference.
Kevin Hufnagleb45780b2017-12-01 16:01:36 -080047 *
Laura Davisb93f8dd2018-08-07 09:53:52 -070048 * <p>For guidance about using shortcuts, see
49 * <a href="/guide/topics/ui/shortcuts/index.html">App shortcuts</a>.
Kevin Hufnagleb45780b2017-12-01 16:01:36 -080050 *
51 * <h3>Retrieving class instances</h3>
52 * <!-- Provides a heading for the content filled in by the @SystemService annotation below -->
Makoto Onuki6f7362d92016-03-04 13:39:41 -080053 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060054@SystemService(Context.SHORTCUT_SERVICE)
Makoto Onuki6f7362d92016-03-04 13:39:41 -080055public class ShortcutManager {
56 private static final String TAG = "ShortcutManager";
57
58 private final Context mContext;
Mathew Inwood45d2c252018-09-14 12:35:36 +010059 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Makoto Onuki6f7362d92016-03-04 13:39:41 -080060 private final IShortcutService mService;
61
62 /**
63 * @hide
64 */
65 public ShortcutManager(Context context, IShortcutService service) {
66 mContext = context;
67 mService = service;
68 }
69
70 /**
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070071 * @hide
72 */
73 @TestApi
74 public ShortcutManager(Context context) {
75 this(context, IShortcutService.Stub.asInterface(
76 ServiceManager.getService(Context.SHORTCUT_SERVICE)));
77 }
78
79 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -070080 * Publish the list of shortcuts. All existing dynamic shortcuts from the caller app
Makoto Onukife9c9662016-07-25 15:12:23 -070081 * will be replaced. If there are already pinned shortcuts with the same IDs,
82 * the mutable pinned shortcuts are updated.
Makoto Onuki6f7362d92016-03-04 13:39:41 -080083 *
84 * <p>This API will be rate-limited.
85 *
86 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
87 *
Makoto Onuki4a910962016-07-07 13:57:34 -070088 * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
Makoto Onukife9c9662016-07-25 15:12:23 -070089 * or when trying to update immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -070090 *
91 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -080092 */
93 public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
94 try {
95 return mService.setDynamicShortcuts(mContext.getPackageName(),
96 new ParceledListSlice(shortcutInfoList), injectMyUserId());
97 } catch (RemoteException e) {
98 throw e.rethrowFromSystemServer();
99 }
100 }
101
102 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700103 * Return all dynamic shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700104 *
Makoto Onukibf563b62017-05-04 10:25:30 -0700105 * <p>This API is intended to be used for examining what shortcuts are currently published.
106 * Re-publishing returned {@link ShortcutInfo}s via APIs such as
107 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
108 *
Makoto Onuki9c850012016-07-26 15:50:50 -0700109 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800110 */
111 @NonNull
112 public List<ShortcutInfo> getDynamicShortcuts() {
113 try {
114 return mService.getDynamicShortcuts(mContext.getPackageName(), injectMyUserId())
115 .getList();
116 } catch (RemoteException e) {
117 throw e.rethrowFromSystemServer();
118 }
119 }
120
121 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700122 * Return all static (manifest) shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700123 *
Makoto Onukibf563b62017-05-04 10:25:30 -0700124 * <p>This API is intended to be used for examining what shortcuts are currently published.
125 * Re-publishing returned {@link ShortcutInfo}s via APIs such as
126 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
127 *
Makoto Onuki9c850012016-07-26 15:50:50 -0700128 * @throws IllegalStateException when the user is locked.
Makoto Onuki22fcc682016-05-17 14:52:19 -0700129 */
130 @NonNull
131 public List<ShortcutInfo> getManifestShortcuts() {
132 try {
133 return mService.getManifestShortcuts(mContext.getPackageName(), injectMyUserId())
134 .getList();
135 } catch (RemoteException e) {
136 throw e.rethrowFromSystemServer();
137 }
138 }
139
140 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700141 * Publish the list of dynamic shortcuts. If there are already dynamic or pinned shortcuts with
142 * the same IDs, each mutable shortcut is updated.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800143 *
144 * <p>This API will be rate-limited.
145 *
146 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
147 *
Makoto Onuki4a910962016-07-07 13:57:34 -0700148 * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
Makoto Onukife9c9662016-07-25 15:12:23 -0700149 * or when trying to update immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700150 *
151 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800152 */
Makoto Onukib6d35232016-04-04 15:57:17 -0700153 public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800154 try {
Makoto Onukib6d35232016-04-04 15:57:17 -0700155 return mService.addDynamicShortcuts(mContext.getPackageName(),
156 new ParceledListSlice(shortcutInfoList), injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800157 } catch (RemoteException e) {
158 throw e.rethrowFromSystemServer();
159 }
160 }
161
162 /**
Makoto Onukic51b2872016-05-04 15:24:50 -0700163 * Delete dynamic shortcuts by ID.
Makoto Onuki9c850012016-07-26 15:50:50 -0700164 *
165 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800166 */
Makoto Onukib6d35232016-04-04 15:57:17 -0700167 public void removeDynamicShortcuts(@NonNull List<String> shortcutIds) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800168 try {
Makoto Onukib6d35232016-04-04 15:57:17 -0700169 mService.removeDynamicShortcuts(mContext.getPackageName(), shortcutIds,
170 injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800171 } catch (RemoteException e) {
172 throw e.rethrowFromSystemServer();
173 }
174 }
175
176 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700177 * Delete all dynamic shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700178 *
179 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800180 */
Makoto Onukib6d35232016-04-04 15:57:17 -0700181 public void removeAllDynamicShortcuts() {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800182 try {
Makoto Onukib6d35232016-04-04 15:57:17 -0700183 mService.removeAllDynamicShortcuts(mContext.getPackageName(), injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800184 } catch (RemoteException e) {
185 throw e.rethrowFromSystemServer();
186 }
187 }
188
189 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700190 * Return all pinned shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700191 *
Makoto Onukibf563b62017-05-04 10:25:30 -0700192 * <p>This API is intended to be used for examining what shortcuts are currently published.
193 * Re-publishing returned {@link ShortcutInfo}s via APIs such as
194 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
195 *
Makoto Onuki9c850012016-07-26 15:50:50 -0700196 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800197 */
198 @NonNull
199 public List<ShortcutInfo> getPinnedShortcuts() {
200 try {
201 return mService.getPinnedShortcuts(mContext.getPackageName(), injectMyUserId())
202 .getList();
203 } catch (RemoteException e) {
204 throw e.rethrowFromSystemServer();
205 }
206 }
207
208 /**
Makoto Onuki4a910962016-07-07 13:57:34 -0700209 * Update all existing shortcuts with the same IDs. Target shortcuts may be pinned and/or
Makoto Onukife9c9662016-07-25 15:12:23 -0700210 * dynamic, but they must not be immutable.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800211 *
212 * <p>This API will be rate-limited.
213 *
214 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
Makoto Onuki4a910962016-07-07 13:57:34 -0700215 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700216 * @throws IllegalArgumentException If trying to update immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700217 *
218 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800219 */
Makoto Onuki2d895c32016-12-02 15:48:40 -0800220 public boolean updateShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800221 try {
222 return mService.updateShortcuts(mContext.getPackageName(),
223 new ParceledListSlice(shortcutInfoList), injectMyUserId());
224 } catch (RemoteException e) {
225 throw e.rethrowFromSystemServer();
226 }
227 }
228
229 /**
Laura Davisb93f8dd2018-08-07 09:53:52 -0700230 * Disable pinned shortcuts. For more details, read
231 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts">
232 * Disable shortcuts</a>.
Makoto Onukife9c9662016-07-25 15:12:23 -0700233 *
234 * @throws IllegalArgumentException If trying to disable immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700235 *
236 * @throws IllegalStateException when the user is locked.
Makoto Onuki20c95f82016-05-11 16:51:01 -0700237 */
238 public void disableShortcuts(@NonNull List<String> shortcutIds) {
239 try {
240 mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
241 /* disabledMessage =*/ null, /* disabledMessageResId =*/ 0,
242 injectMyUserId());
243 } catch (RemoteException e) {
244 throw e.rethrowFromSystemServer();
245 }
246 }
247
248 /**
Makoto Onukid6880792016-06-29 13:37:43 -0700249 * @hide old signature, kept for unit testing.
Makoto Onuki20c95f82016-05-11 16:51:01 -0700250 */
251 public void disableShortcuts(@NonNull List<String> shortcutIds, int disabledMessageResId) {
252 try {
253 mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
254 /* disabledMessage =*/ null, disabledMessageResId,
255 injectMyUserId());
256 } catch (RemoteException e) {
257 throw e.rethrowFromSystemServer();
258 }
259 }
260
261 /**
Makoto Onukid6880792016-06-29 13:37:43 -0700262 * @hide old signature, kept for unit testing.
Makoto Onuki20c95f82016-05-11 16:51:01 -0700263 */
264 public void disableShortcuts(@NonNull List<String> shortcutIds, String disabledMessage) {
Makoto Onukid6880792016-06-29 13:37:43 -0700265 disableShortcuts(shortcutIds, (CharSequence) disabledMessage);
266 }
267
268 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700269 * Disable pinned shortcuts, showing the user a custom error message when they try to select
270 * the disabled shortcuts.
Laura Davisb93f8dd2018-08-07 09:53:52 -0700271 * For more details, read
272 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts">
273 * Disable shortcuts</a>.
Makoto Onukife9c9662016-07-25 15:12:23 -0700274 *
275 * @throws IllegalArgumentException If trying to disable immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700276 *
277 * @throws IllegalStateException when the user is locked.
Makoto Onukid6880792016-06-29 13:37:43 -0700278 */
279 public void disableShortcuts(@NonNull List<String> shortcutIds, CharSequence disabledMessage) {
Makoto Onuki20c95f82016-05-11 16:51:01 -0700280 try {
281 mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
282 disabledMessage, /* disabledMessageResId =*/ 0,
283 injectMyUserId());
284 } catch (RemoteException e) {
285 throw e.rethrowFromSystemServer();
286 }
287 }
288
289 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700290 * Re-enable pinned shortcuts that were previously disabled. If the target shortcuts
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700291 * are already enabled, this method does nothing.
Makoto Onukife9c9662016-07-25 15:12:23 -0700292 *
293 * @throws IllegalArgumentException If trying to enable immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700294 *
295 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800296 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700297 public void enableShortcuts(@NonNull List<String> shortcutIds) {
298 try {
299 mService.enableShortcuts(mContext.getPackageName(), shortcutIds, injectMyUserId());
300 } catch (RemoteException e) {
301 throw e.rethrowFromSystemServer();
302 }
303 }
304
Makoto Onukid6880792016-06-29 13:37:43 -0700305
306 /**
307 * @hide old signature, kept for unit testing.
308 */
309 public int getMaxShortcutCountForActivity() {
310 return getMaxShortcutCountPerActivity();
311 }
312
Makoto Onuki22fcc682016-05-17 14:52:19 -0700313 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700314 * Return the maximum number of static and dynamic shortcuts that each launcher icon
Makoto Onuki22fcc682016-05-17 14:52:19 -0700315 * can have at a time.
316 */
Makoto Onukid6880792016-06-29 13:37:43 -0700317 public int getMaxShortcutCountPerActivity() {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800318 try {
Makoto Onukid6880792016-06-29 13:37:43 -0700319 return mService.getMaxShortcutCountPerActivity(
Makoto Onukib5a012f2016-06-21 11:13:53 -0700320 mContext.getPackageName(), injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800321 } catch (RemoteException e) {
322 throw e.rethrowFromSystemServer();
323 }
324 }
325
326 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700327 * Return the number of times the caller app can call the rate-limited APIs
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800328 * before the rate limit counter is reset.
329 *
330 * @see #getRateLimitResetTime()
Makoto Onukif805b432016-07-07 11:51:52 -0700331 *
332 * @hide
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800333 */
334 public int getRemainingCallCount() {
335 try {
336 return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId());
337 } catch (RemoteException e) {
338 throw e.rethrowFromSystemServer();
339 }
340 }
341
342 /**
343 * Return when the rate limit count will be reset next time, in milliseconds since the epoch.
344 *
345 * @see #getRemainingCallCount()
346 * @see System#currentTimeMillis()
Makoto Onukif805b432016-07-07 11:51:52 -0700347 *
348 * @hide
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800349 */
350 public long getRateLimitResetTime() {
351 try {
352 return mService.getRateLimitResetTime(mContext.getPackageName(), injectMyUserId());
353 } catch (RemoteException e) {
354 throw e.rethrowFromSystemServer();
355 }
356 }
357
Makoto Onuki55046222016-03-08 10:49:47 -0800358 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700359 * Return {@code true} when rate-limiting is active for the caller app.
Makoto Onuki347a6bd2016-07-19 11:13:08 -0700360 *
Laura Davisb93f8dd2018-08-07 09:53:52 -0700361 * <p>For details, see <a href="/guide/topics/ui/shortcuts/managing-shortcuts#rate-limiting">
362 * Rate limiting</a>.
Makoto Onuki9c850012016-07-26 15:50:50 -0700363 *
364 * @throws IllegalStateException when the user is locked.
Makoto Onuki347a6bd2016-07-19 11:13:08 -0700365 */
366 public boolean isRateLimitingActive() {
367 try {
368 return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId())
369 == 0;
370 } catch (RemoteException e) {
371 throw e.rethrowFromSystemServer();
372 }
373 }
374
375 /**
Makoto Onuki22fcc682016-05-17 14:52:19 -0700376 * Return the max width for icons, in pixels.
Hyunyoung Song47037462017-05-08 16:51:43 -0700377 *
378 * <p> Note that this method returns max width of icon's visible part. Hence, it does not take
379 * into account the inset introduced by {@link AdaptiveIconDrawable}. To calculate bitmap image
Makoto Onuki9aeff8a2017-05-30 16:50:20 -0700380 * to function as {@link AdaptiveIconDrawable}, multiply
Hyunyoung Song47037462017-05-08 16:51:43 -0700381 * 1 + 2 * {@link AdaptiveIconDrawable#getExtraInsetFraction()} to the returned size.
Makoto Onuki55046222016-03-08 10:49:47 -0800382 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700383 public int getIconMaxWidth() {
Makoto Onuki55046222016-03-08 10:49:47 -0800384 try {
Makoto Onuki22fcc682016-05-17 14:52:19 -0700385 // TODO Implement it properly using xdpi.
386 return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId());
387 } catch (RemoteException e) {
388 throw e.rethrowFromSystemServer();
389 }
390 }
391
392 /**
393 * Return the max height for icons, in pixels.
394 */
395 public int getIconMaxHeight() {
396 try {
397 // TODO Implement it properly using ydpi.
Makoto Onuki55046222016-03-08 10:49:47 -0800398 return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId());
399 } catch (RemoteException e) {
400 throw e.rethrowFromSystemServer();
401 }
402 }
403
Makoto Onukiac042502016-05-20 16:39:42 -0700404 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700405 * Apps that publish shortcuts should call this method whenever the user
406 * selects the shortcut containing the given ID or when the user completes
407 * an action in the app that is equivalent to selecting the shortcut.
Laura Davisb93f8dd2018-08-07 09:53:52 -0700408 * For more details, read about
409 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#track-usage">
410 * tracking shortcut usage</a>.
Makoto Onukiac042502016-05-20 16:39:42 -0700411 *
412 * <p>The information is accessible via {@link UsageStatsManager#queryEvents}
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700413 * Typically, launcher apps use this information to build a prediction model
Makoto Onukiac042502016-05-20 16:39:42 -0700414 * so that they can promote the shortcuts that are likely to be used at the moment.
Makoto Onuki9c850012016-07-26 15:50:50 -0700415 *
416 * @throws IllegalStateException when the user is locked.
Makoto Onukiac042502016-05-20 16:39:42 -0700417 */
Makoto Onuki20c95f82016-05-11 16:51:01 -0700418 public void reportShortcutUsed(String shortcutId) {
419 try {
420 mService.reportShortcutUsed(mContext.getPackageName(), shortcutId,
421 injectMyUserId());
422 } catch (RemoteException e) {
423 throw e.rethrowFromSystemServer();
424 }
425 }
426
Makoto Onukid6e1f3b2016-06-14 11:17:59 -0700427 /**
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700428 * Return {@code TRUE} if the app is running on a device whose default launcher supports
Makoto Onuki2d895c32016-12-02 15:48:40 -0800429 * {@link #requestPinShortcut(ShortcutInfo, IntentSender)}.
Makoto Onuki16e83d02017-04-17 10:55:21 -0700430 *
Makoto Onuki9aeff8a2017-05-30 16:50:20 -0700431 * <p>The return value may change in subsequent calls if the user changes the default launcher
432 * app.
433 *
434 * <p><b>Note:</b> See also the support library counterpart
435 * {@link android.support.v4.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported(
436 * Context)}, which supports Android versions lower than {@link VERSION_CODES#O} using the
437 * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
438 *
439 * @see #requestPinShortcut(ShortcutInfo, IntentSender)
Makoto Onuki2d895c32016-12-02 15:48:40 -0800440 */
441 public boolean isRequestPinShortcutSupported() {
442 try {
Sunny Goyal7f7372a2017-01-24 11:53:54 -0800443 return mService.isRequestPinItemSupported(injectMyUserId(),
444 LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT);
Makoto Onuki2d895c32016-12-02 15:48:40 -0800445 } catch (RemoteException e) {
446 throw e.rethrowFromSystemServer();
447 }
448 }
449
450 /**
451 * Request to create a pinned shortcut. The default launcher will receive this request and
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700452 * ask the user for approval. If the user approves it, the shortcut will be created, and
453 * {@code resultIntent} will be sent. If a request is denied by the user, however, no response
454 * will be sent to the caller.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800455 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700456 * <p>Only apps with a foreground activity or a foreground service can call this method.
457 * Otherwise, it'll throw {@link IllegalStateException}.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800458 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700459 * <p>It's up to the launcher to decide how to handle previous pending requests when the same
460 * package calls this API multiple times in a row. One possible strategy is to ignore any
461 * previous requests.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800462 *
Makoto Onuki9aeff8a2017-05-30 16:50:20 -0700463 * <p><b>Note:</b> See also the support library counterpart
464 * {@link android.support.v4.content.pm.ShortcutManagerCompat#requestPinShortcut(
465 * Context, ShortcutInfoCompat, IntentSender)},
466 * which supports Android versions lower than {@link VERSION_CODES#O} using the
467 * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
468 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700469 * @param shortcut Shortcut to pin. If an app wants to pin an existing (either static
470 * or dynamic) shortcut, then it only needs to have an ID. Although other fields don't have
471 * to be set, the target shortcut must be enabled.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800472 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700473 * <p>If it's a new shortcut, all the mandatory fields, such as a short label, must be
Makoto Onuki2d895c32016-12-02 15:48:40 -0800474 * set.
475 * @param resultIntent If not null, this intent will be sent when the shortcut is pinned.
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700476 * Use {@link android.app.PendingIntent#getIntentSender()} to create an {@link IntentSender}.
Makoto Onuki16e83d02017-04-17 10:55:21 -0700477 * To avoid background execution limits, use an unexported, manifest-declared receiver.
Laura Davisb93f8dd2018-08-07 09:53:52 -0700478 * For more details, see
479 * <a href="/guide/topics/ui/shortcuts/creating-shortcuts.html#pinned">
480 * Creating pinned shortcuts</a>.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800481 *
482 * @return {@code TRUE} if the launcher supports this feature. Note the API will return without
483 * waiting for the user to respond, so getting {@code TRUE} from this API does *not* mean
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700484 * the shortcut was pinned successfully. {@code FALSE} if the launcher doesn't support this
485 * feature.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800486 *
487 * @see #isRequestPinShortcutSupported()
488 * @see IntentSender
489 * @see android.app.PendingIntent#getIntentSender()
490 *
491 * @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled.
492 * @throws IllegalStateException The caller doesn't have a foreground activity or a foreground
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700493 * service, or the device is locked.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800494 */
495 public boolean requestPinShortcut(@NonNull ShortcutInfo shortcut,
496 @Nullable IntentSender resultIntent) {
497 try {
498 return mService.requestPinShortcut(mContext.getPackageName(), shortcut,
499 resultIntent, injectMyUserId());
500 } catch (RemoteException e) {
501 throw e.rethrowFromSystemServer();
502 }
503 }
504
505 /**
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700506 * Returns an Intent which can be used by the default launcher to pin a shortcut containing the
507 * given {@link ShortcutInfo}. This method should be used by an Activity to set a result in
508 * response to {@link Intent#ACTION_CREATE_SHORTCUT}.
Sunny Goyala6be88a2017-01-12 16:27:58 -0800509 *
510 * @param shortcut New shortcut to pin. If an app wants to pin an existing (either dynamic
511 * or manifest) shortcut, then it only needs to have an ID, and other fields don't have to
512 * be set, in which case, the target shortcut must be enabled.
513 * If it's a new shortcut, all the mandatory fields, such as a short label, must be
514 * set.
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700515 * @return The intent that should be set as the result for the calling activity, or
516 * <code>null</code> if the current launcher doesn't support shortcuts.
Sunny Goyala6be88a2017-01-12 16:27:58 -0800517 *
518 * @see Intent#ACTION_CREATE_SHORTCUT
519 *
520 * @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled.
521 */
522 public Intent createShortcutResultIntent(@NonNull ShortcutInfo shortcut) {
523 try {
524 return mService.createShortcutResultIntent(mContext.getPackageName(), shortcut,
525 injectMyUserId());
526 } catch (RemoteException e) {
527 throw e.rethrowFromSystemServer();
528 }
529 }
530
531 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700532 * Called internally when an app is considered to have come to the foreground
Makoto Onukid6e1f3b2016-06-14 11:17:59 -0700533 * even when technically it's not. This method resets the throttling for this package.
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700534 * For example, when the user sends an "inline reply" on a notification, the system UI will
Makoto Onukid6e1f3b2016-06-14 11:17:59 -0700535 * call it.
536 *
537 * @hide
538 */
539 public void onApplicationActive(@NonNull String packageName, @UserIdInt int userId) {
540 try {
541 mService.onApplicationActive(packageName, userId);
542 } catch (RemoteException e) {
543 throw e.rethrowFromSystemServer();
544 }
545 }
546
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800547 /** @hide injection point */
548 @VisibleForTesting
549 protected int injectMyUserId() {
Jeff Sharkeyad357d12018-02-02 13:25:31 -0700550 return mContext.getUserId();
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800551 }
552}