blob: dde8865467a170c822e66cd69fbd87c2708dc6b0 [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
Sunny Goyalddd089a2019-03-21 12:45:43 -070018import android.Manifest;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080019import android.annotation.NonNull;
Makoto Onuki2d895c32016-12-02 15:48:40 -080020import android.annotation.Nullable;
Sunny Goyalddd089a2019-03-21 12:45:43 -070021import android.annotation.RequiresPermission;
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -080022import android.annotation.SystemApi;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060023import android.annotation.SystemService;
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070024import android.annotation.TestApi;
Makoto Onukid6e1f3b2016-06-14 11:17:59 -070025import android.annotation.UserIdInt;
Makoto Onukiac042502016-05-20 16:39:42 -070026import android.app.usage.UsageStatsManager;
Artur Satayeve23a0eb2019-12-10 17:47:52 +000027import android.compat.annotation.UnsupportedAppUsage;
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -080028import android.content.ComponentName;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080029import android.content.Context;
Makoto Onuki4a910962016-07-07 13:57:34 -070030import android.content.Intent;
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -080031import android.content.IntentFilter;
Makoto Onuki2d895c32016-12-02 15:48:40 -080032import android.content.IntentSender;
Makoto Onuki9aeff8a2017-05-30 16:50:20 -070033import android.graphics.drawable.AdaptiveIconDrawable;
Mathew Inwood8c854f82018-09-14 12:35:36 +010034import android.os.Build;
Makoto Onuki16e83d02017-04-17 10:55:21 -070035import android.os.Build.VERSION_CODES;
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -080036import android.os.Parcel;
37import android.os.Parcelable;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080038import android.os.RemoteException;
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070039import android.os.ServiceManager;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080040
41import com.android.internal.annotations.VisibleForTesting;
42
43import java.util.List;
44
45/**
Laura Davisb93f8dd2018-08-07 09:53:52 -070046 * <p><code>ShortcutManager</code> executes operations on an app's set of <i>shortcuts</i>, which
47 * represent specific tasks and actions that users can perform within your app. This page lists
48 * components of the <code>ShortcutManager</code> class that you can use to create and manage
49 * sets of shortcuts.
Kevin Hufnagleb45780b2017-12-01 16:01:36 -080050 *
Laura Davisb93f8dd2018-08-07 09:53:52 -070051 * <p>To learn about methods that retrieve information about a single shortcut&mdash;including
52 * identifiers, type, and status&mdash;read the <code>
53 * <a href="/reference/android/content/pm/ShortcutInfo.html">ShortcutInfo</a></code> reference.
Kevin Hufnagleb45780b2017-12-01 16:01:36 -080054 *
Laura Davisb93f8dd2018-08-07 09:53:52 -070055 * <p>For guidance about using shortcuts, see
56 * <a href="/guide/topics/ui/shortcuts/index.html">App shortcuts</a>.
Kevin Hufnagleb45780b2017-12-01 16:01:36 -080057 *
58 * <h3>Retrieving class instances</h3>
59 * <!-- Provides a heading for the content filled in by the @SystemService annotation below -->
Makoto Onuki6f7362d92016-03-04 13:39:41 -080060 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060061@SystemService(Context.SHORTCUT_SERVICE)
Makoto Onuki6f7362d92016-03-04 13:39:41 -080062public class ShortcutManager {
63 private static final String TAG = "ShortcutManager";
64
65 private final Context mContext;
Mathew Inwood8c854f82018-09-14 12:35:36 +010066 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Makoto Onuki6f7362d92016-03-04 13:39:41 -080067 private final IShortcutService mService;
68
69 /**
70 * @hide
71 */
72 public ShortcutManager(Context context, IShortcutService service) {
73 mContext = context;
74 mService = service;
75 }
76
77 /**
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070078 * @hide
79 */
80 @TestApi
81 public ShortcutManager(Context context) {
82 this(context, IShortcutService.Stub.asInterface(
83 ServiceManager.getService(Context.SHORTCUT_SERVICE)));
84 }
85
86 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -070087 * Publish the list of shortcuts. All existing dynamic shortcuts from the caller app
Makoto Onukife9c9662016-07-25 15:12:23 -070088 * will be replaced. If there are already pinned shortcuts with the same IDs,
89 * the mutable pinned shortcuts are updated.
Makoto Onuki6f7362d92016-03-04 13:39:41 -080090 *
91 * <p>This API will be rate-limited.
92 *
93 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
94 *
Makoto Onuki4a910962016-07-07 13:57:34 -070095 * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
Makoto Onukife9c9662016-07-25 15:12:23 -070096 * or when trying to update immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -070097 *
98 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -080099 */
100 public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
101 try {
102 return mService.setDynamicShortcuts(mContext.getPackageName(),
103 new ParceledListSlice(shortcutInfoList), injectMyUserId());
104 } catch (RemoteException e) {
105 throw e.rethrowFromSystemServer();
106 }
107 }
108
109 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700110 * Return all dynamic shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700111 *
Makoto Onukibf563b62017-05-04 10:25:30 -0700112 * <p>This API is intended to be used for examining what shortcuts are currently published.
113 * Re-publishing returned {@link ShortcutInfo}s via APIs such as
114 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
115 *
Makoto Onuki9c850012016-07-26 15:50:50 -0700116 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800117 */
118 @NonNull
119 public List<ShortcutInfo> getDynamicShortcuts() {
120 try {
121 return mService.getDynamicShortcuts(mContext.getPackageName(), injectMyUserId())
122 .getList();
123 } catch (RemoteException e) {
124 throw e.rethrowFromSystemServer();
125 }
126 }
127
128 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700129 * Return all static (manifest) shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700130 *
Makoto Onukibf563b62017-05-04 10:25:30 -0700131 * <p>This API is intended to be used for examining what shortcuts are currently published.
132 * Re-publishing returned {@link ShortcutInfo}s via APIs such as
133 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
134 *
Makoto Onuki9c850012016-07-26 15:50:50 -0700135 * @throws IllegalStateException when the user is locked.
Makoto Onuki22fcc682016-05-17 14:52:19 -0700136 */
137 @NonNull
138 public List<ShortcutInfo> getManifestShortcuts() {
139 try {
140 return mService.getManifestShortcuts(mContext.getPackageName(), injectMyUserId())
141 .getList();
142 } catch (RemoteException e) {
143 throw e.rethrowFromSystemServer();
144 }
145 }
146
147 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700148 * Publish the list of dynamic shortcuts. If there are already dynamic or pinned shortcuts with
149 * the same IDs, each mutable shortcut is updated.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800150 *
151 * <p>This API will be rate-limited.
152 *
153 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
154 *
Makoto Onuki4a910962016-07-07 13:57:34 -0700155 * @throws IllegalArgumentException if {@link #getMaxShortcutCountPerActivity()} is exceeded,
Makoto Onukife9c9662016-07-25 15:12:23 -0700156 * or when trying to update immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700157 *
158 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800159 */
Makoto Onukib6d35232016-04-04 15:57:17 -0700160 public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800161 try {
Makoto Onukib6d35232016-04-04 15:57:17 -0700162 return mService.addDynamicShortcuts(mContext.getPackageName(),
163 new ParceledListSlice(shortcutInfoList), injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800164 } catch (RemoteException e) {
165 throw e.rethrowFromSystemServer();
166 }
167 }
168
169 /**
Makoto Onukic51b2872016-05-04 15:24:50 -0700170 * Delete dynamic shortcuts by ID.
Makoto Onuki9c850012016-07-26 15:50:50 -0700171 *
172 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800173 */
Makoto Onukib6d35232016-04-04 15:57:17 -0700174 public void removeDynamicShortcuts(@NonNull List<String> shortcutIds) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800175 try {
Makoto Onukib6d35232016-04-04 15:57:17 -0700176 mService.removeDynamicShortcuts(mContext.getPackageName(), shortcutIds,
177 injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800178 } catch (RemoteException e) {
179 throw e.rethrowFromSystemServer();
180 }
181 }
182
183 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700184 * Delete all dynamic shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700185 *
186 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800187 */
Makoto Onukib6d35232016-04-04 15:57:17 -0700188 public void removeAllDynamicShortcuts() {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800189 try {
Makoto Onukib6d35232016-04-04 15:57:17 -0700190 mService.removeAllDynamicShortcuts(mContext.getPackageName(), injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800191 } catch (RemoteException e) {
192 throw e.rethrowFromSystemServer();
193 }
194 }
195
196 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700197 * Return all pinned shortcuts from the caller app.
Makoto Onuki9c850012016-07-26 15:50:50 -0700198 *
Makoto Onukibf563b62017-05-04 10:25:30 -0700199 * <p>This API is intended to be used for examining what shortcuts are currently published.
200 * Re-publishing returned {@link ShortcutInfo}s via APIs such as
201 * {@link #setDynamicShortcuts(List)} may cause loss of information such as icons.
202 *
Makoto Onuki9c850012016-07-26 15:50:50 -0700203 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800204 */
205 @NonNull
206 public List<ShortcutInfo> getPinnedShortcuts() {
207 try {
208 return mService.getPinnedShortcuts(mContext.getPackageName(), injectMyUserId())
209 .getList();
210 } catch (RemoteException e) {
211 throw e.rethrowFromSystemServer();
212 }
213 }
214
215 /**
Makoto Onuki4a910962016-07-07 13:57:34 -0700216 * Update all existing shortcuts with the same IDs. Target shortcuts may be pinned and/or
Makoto Onukife9c9662016-07-25 15:12:23 -0700217 * dynamic, but they must not be immutable.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800218 *
219 * <p>This API will be rate-limited.
220 *
221 * @return {@code true} if the call has succeeded. {@code false} if the call is rate-limited.
Makoto Onuki4a910962016-07-07 13:57:34 -0700222 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700223 * @throws IllegalArgumentException If trying to update immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700224 *
225 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800226 */
Makoto Onuki2d895c32016-12-02 15:48:40 -0800227 public boolean updateShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800228 try {
229 return mService.updateShortcuts(mContext.getPackageName(),
230 new ParceledListSlice(shortcutInfoList), injectMyUserId());
231 } catch (RemoteException e) {
232 throw e.rethrowFromSystemServer();
233 }
234 }
235
236 /**
Laura Davisb93f8dd2018-08-07 09:53:52 -0700237 * Disable pinned shortcuts. For more details, read
238 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts">
239 * Disable shortcuts</a>.
Makoto Onukife9c9662016-07-25 15:12:23 -0700240 *
241 * @throws IllegalArgumentException If trying to disable immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700242 *
243 * @throws IllegalStateException when the user is locked.
Makoto Onuki20c95f82016-05-11 16:51:01 -0700244 */
245 public void disableShortcuts(@NonNull List<String> shortcutIds) {
246 try {
247 mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
248 /* disabledMessage =*/ null, /* disabledMessageResId =*/ 0,
249 injectMyUserId());
250 } catch (RemoteException e) {
251 throw e.rethrowFromSystemServer();
252 }
253 }
254
255 /**
Makoto Onukid6880792016-06-29 13:37:43 -0700256 * @hide old signature, kept for unit testing.
Makoto Onuki20c95f82016-05-11 16:51:01 -0700257 */
258 public void disableShortcuts(@NonNull List<String> shortcutIds, int disabledMessageResId) {
259 try {
260 mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
261 /* disabledMessage =*/ null, disabledMessageResId,
262 injectMyUserId());
263 } catch (RemoteException e) {
264 throw e.rethrowFromSystemServer();
265 }
266 }
267
268 /**
Makoto Onukid6880792016-06-29 13:37:43 -0700269 * @hide old signature, kept for unit testing.
Makoto Onuki20c95f82016-05-11 16:51:01 -0700270 */
271 public void disableShortcuts(@NonNull List<String> shortcutIds, String disabledMessage) {
Makoto Onukid6880792016-06-29 13:37:43 -0700272 disableShortcuts(shortcutIds, (CharSequence) disabledMessage);
273 }
274
275 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700276 * Disable pinned shortcuts, showing the user a custom error message when they try to select
277 * the disabled shortcuts.
Laura Davisb93f8dd2018-08-07 09:53:52 -0700278 * For more details, read
279 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#disable-shortcuts">
280 * Disable shortcuts</a>.
Makoto Onukife9c9662016-07-25 15:12:23 -0700281 *
282 * @throws IllegalArgumentException If trying to disable immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700283 *
284 * @throws IllegalStateException when the user is locked.
Makoto Onukid6880792016-06-29 13:37:43 -0700285 */
286 public void disableShortcuts(@NonNull List<String> shortcutIds, CharSequence disabledMessage) {
Makoto Onuki20c95f82016-05-11 16:51:01 -0700287 try {
288 mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
289 disabledMessage, /* disabledMessageResId =*/ 0,
290 injectMyUserId());
291 } catch (RemoteException e) {
292 throw e.rethrowFromSystemServer();
293 }
294 }
295
296 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700297 * Re-enable pinned shortcuts that were previously disabled. If the target shortcuts
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700298 * are already enabled, this method does nothing.
Makoto Onukife9c9662016-07-25 15:12:23 -0700299 *
300 * @throws IllegalArgumentException If trying to enable immutable shortcuts.
Makoto Onuki9c850012016-07-26 15:50:50 -0700301 *
302 * @throws IllegalStateException when the user is locked.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800303 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700304 public void enableShortcuts(@NonNull List<String> shortcutIds) {
305 try {
306 mService.enableShortcuts(mContext.getPackageName(), shortcutIds, injectMyUserId());
307 } catch (RemoteException e) {
308 throw e.rethrowFromSystemServer();
309 }
310 }
311
Makoto Onukid6880792016-06-29 13:37:43 -0700312
313 /**
314 * @hide old signature, kept for unit testing.
315 */
316 public int getMaxShortcutCountForActivity() {
317 return getMaxShortcutCountPerActivity();
318 }
319
Makoto Onuki22fcc682016-05-17 14:52:19 -0700320 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700321 * Return the maximum number of static and dynamic shortcuts that each launcher icon
Makoto Onuki22fcc682016-05-17 14:52:19 -0700322 * can have at a time.
323 */
Makoto Onukid6880792016-06-29 13:37:43 -0700324 public int getMaxShortcutCountPerActivity() {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800325 try {
Makoto Onukid6880792016-06-29 13:37:43 -0700326 return mService.getMaxShortcutCountPerActivity(
Makoto Onukib5a012f2016-06-21 11:13:53 -0700327 mContext.getPackageName(), injectMyUserId());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800328 } catch (RemoteException e) {
329 throw e.rethrowFromSystemServer();
330 }
331 }
332
333 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700334 * Return the number of times the caller app can call the rate-limited APIs
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800335 * before the rate limit counter is reset.
336 *
337 * @see #getRateLimitResetTime()
Makoto Onukif805b432016-07-07 11:51:52 -0700338 *
339 * @hide
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800340 */
341 public int getRemainingCallCount() {
342 try {
343 return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId());
344 } catch (RemoteException e) {
345 throw e.rethrowFromSystemServer();
346 }
347 }
348
349 /**
350 * Return when the rate limit count will be reset next time, in milliseconds since the epoch.
351 *
352 * @see #getRemainingCallCount()
353 * @see System#currentTimeMillis()
Makoto Onukif805b432016-07-07 11:51:52 -0700354 *
355 * @hide
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800356 */
357 public long getRateLimitResetTime() {
358 try {
359 return mService.getRateLimitResetTime(mContext.getPackageName(), injectMyUserId());
360 } catch (RemoteException e) {
361 throw e.rethrowFromSystemServer();
362 }
363 }
364
Makoto Onuki55046222016-03-08 10:49:47 -0800365 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700366 * Return {@code true} when rate-limiting is active for the caller app.
Makoto Onuki347a6bd2016-07-19 11:13:08 -0700367 *
Laura Davisb93f8dd2018-08-07 09:53:52 -0700368 * <p>For details, see <a href="/guide/topics/ui/shortcuts/managing-shortcuts#rate-limiting">
369 * Rate limiting</a>.
Makoto Onuki9c850012016-07-26 15:50:50 -0700370 *
371 * @throws IllegalStateException when the user is locked.
Makoto Onuki347a6bd2016-07-19 11:13:08 -0700372 */
373 public boolean isRateLimitingActive() {
374 try {
375 return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId())
376 == 0;
377 } catch (RemoteException e) {
378 throw e.rethrowFromSystemServer();
379 }
380 }
381
382 /**
Makoto Onuki22fcc682016-05-17 14:52:19 -0700383 * Return the max width for icons, in pixels.
Hyunyoung Song47037462017-05-08 16:51:43 -0700384 *
385 * <p> Note that this method returns max width of icon's visible part. Hence, it does not take
386 * into account the inset introduced by {@link AdaptiveIconDrawable}. To calculate bitmap image
Makoto Onuki9aeff8a2017-05-30 16:50:20 -0700387 * to function as {@link AdaptiveIconDrawable}, multiply
Hyunyoung Song47037462017-05-08 16:51:43 -0700388 * 1 + 2 * {@link AdaptiveIconDrawable#getExtraInsetFraction()} to the returned size.
Makoto Onuki55046222016-03-08 10:49:47 -0800389 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700390 public int getIconMaxWidth() {
Makoto Onuki55046222016-03-08 10:49:47 -0800391 try {
Makoto Onuki22fcc682016-05-17 14:52:19 -0700392 // TODO Implement it properly using xdpi.
393 return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId());
394 } catch (RemoteException e) {
395 throw e.rethrowFromSystemServer();
396 }
397 }
398
399 /**
400 * Return the max height for icons, in pixels.
401 */
402 public int getIconMaxHeight() {
403 try {
404 // TODO Implement it properly using ydpi.
Makoto Onuki55046222016-03-08 10:49:47 -0800405 return mService.getIconMaxDimensions(mContext.getPackageName(), injectMyUserId());
406 } catch (RemoteException e) {
407 throw e.rethrowFromSystemServer();
408 }
409 }
410
Makoto Onukiac042502016-05-20 16:39:42 -0700411 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700412 * Apps that publish shortcuts should call this method whenever the user
413 * selects the shortcut containing the given ID or when the user completes
414 * an action in the app that is equivalent to selecting the shortcut.
Laura Davisb93f8dd2018-08-07 09:53:52 -0700415 * For more details, read about
416 * <a href="/guide/topics/ui/shortcuts/managing-shortcuts.html#track-usage">
417 * tracking shortcut usage</a>.
Makoto Onukiac042502016-05-20 16:39:42 -0700418 *
419 * <p>The information is accessible via {@link UsageStatsManager#queryEvents}
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700420 * Typically, launcher apps use this information to build a prediction model
Makoto Onukiac042502016-05-20 16:39:42 -0700421 * so that they can promote the shortcuts that are likely to be used at the moment.
Makoto Onuki9c850012016-07-26 15:50:50 -0700422 *
423 * @throws IllegalStateException when the user is locked.
Makoto Onukiac042502016-05-20 16:39:42 -0700424 */
Makoto Onuki20c95f82016-05-11 16:51:01 -0700425 public void reportShortcutUsed(String shortcutId) {
426 try {
427 mService.reportShortcutUsed(mContext.getPackageName(), shortcutId,
428 injectMyUserId());
429 } catch (RemoteException e) {
430 throw e.rethrowFromSystemServer();
431 }
432 }
433
Makoto Onukid6e1f3b2016-06-14 11:17:59 -0700434 /**
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700435 * Return {@code TRUE} if the app is running on a device whose default launcher supports
Makoto Onuki2d895c32016-12-02 15:48:40 -0800436 * {@link #requestPinShortcut(ShortcutInfo, IntentSender)}.
Makoto Onuki16e83d02017-04-17 10:55:21 -0700437 *
Makoto Onuki9aeff8a2017-05-30 16:50:20 -0700438 * <p>The return value may change in subsequent calls if the user changes the default launcher
439 * app.
440 *
441 * <p><b>Note:</b> See also the support library counterpart
442 * {@link android.support.v4.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported(
443 * Context)}, which supports Android versions lower than {@link VERSION_CODES#O} using the
444 * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
445 *
446 * @see #requestPinShortcut(ShortcutInfo, IntentSender)
Makoto Onuki2d895c32016-12-02 15:48:40 -0800447 */
448 public boolean isRequestPinShortcutSupported() {
449 try {
Sunny Goyal7f7372a2017-01-24 11:53:54 -0800450 return mService.isRequestPinItemSupported(injectMyUserId(),
451 LauncherApps.PinItemRequest.REQUEST_TYPE_SHORTCUT);
Makoto Onuki2d895c32016-12-02 15:48:40 -0800452 } catch (RemoteException e) {
453 throw e.rethrowFromSystemServer();
454 }
455 }
456
457 /**
458 * Request to create a pinned shortcut. The default launcher will receive this request and
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700459 * ask the user for approval. If the user approves it, the shortcut will be created, and
460 * {@code resultIntent} will be sent. If a request is denied by the user, however, no response
461 * will be sent to the caller.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800462 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700463 * <p>Only apps with a foreground activity or a foreground service can call this method.
464 * Otherwise, it'll throw {@link IllegalStateException}.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800465 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700466 * <p>It's up to the launcher to decide how to handle previous pending requests when the same
467 * package calls this API multiple times in a row. One possible strategy is to ignore any
468 * previous requests.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800469 *
Makoto Onuki9aeff8a2017-05-30 16:50:20 -0700470 * <p><b>Note:</b> See also the support library counterpart
471 * {@link android.support.v4.content.pm.ShortcutManagerCompat#requestPinShortcut(
472 * Context, ShortcutInfoCompat, IntentSender)},
473 * which supports Android versions lower than {@link VERSION_CODES#O} using the
474 * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
475 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700476 * @param shortcut Shortcut to pin. If an app wants to pin an existing (either static
477 * or dynamic) shortcut, then it only needs to have an ID. Although other fields don't have
478 * to be set, the target shortcut must be enabled.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800479 *
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700480 * <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 -0800481 * set.
482 * @param resultIntent If not null, this intent will be sent when the shortcut is pinned.
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700483 * Use {@link android.app.PendingIntent#getIntentSender()} to create an {@link IntentSender}.
Makoto Onuki16e83d02017-04-17 10:55:21 -0700484 * To avoid background execution limits, use an unexported, manifest-declared receiver.
Laura Davisb93f8dd2018-08-07 09:53:52 -0700485 * For more details, see
486 * <a href="/guide/topics/ui/shortcuts/creating-shortcuts.html#pinned">
487 * Creating pinned shortcuts</a>.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800488 *
489 * @return {@code TRUE} if the launcher supports this feature. Note the API will return without
490 * waiting for the user to respond, so getting {@code TRUE} from this API does *not* mean
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700491 * the shortcut was pinned successfully. {@code FALSE} if the launcher doesn't support this
492 * feature.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800493 *
494 * @see #isRequestPinShortcutSupported()
495 * @see IntentSender
496 * @see android.app.PendingIntent#getIntentSender()
497 *
498 * @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled.
499 * @throws IllegalStateException The caller doesn't have a foreground activity or a foreground
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700500 * service, or the device is locked.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800501 */
502 public boolean requestPinShortcut(@NonNull ShortcutInfo shortcut,
503 @Nullable IntentSender resultIntent) {
504 try {
505 return mService.requestPinShortcut(mContext.getPackageName(), shortcut,
506 resultIntent, injectMyUserId());
507 } catch (RemoteException e) {
508 throw e.rethrowFromSystemServer();
509 }
510 }
511
512 /**
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700513 * Returns an Intent which can be used by the default launcher to pin a shortcut containing the
514 * given {@link ShortcutInfo}. This method should be used by an Activity to set a result in
515 * response to {@link Intent#ACTION_CREATE_SHORTCUT}.
Sunny Goyala6be88a2017-01-12 16:27:58 -0800516 *
517 * @param shortcut New shortcut to pin. If an app wants to pin an existing (either dynamic
518 * or manifest) shortcut, then it only needs to have an ID, and other fields don't have to
519 * be set, in which case, the target shortcut must be enabled.
520 * If it's a new shortcut, all the mandatory fields, such as a short label, must be
521 * set.
Kevin Hufnagle652438c2017-03-17 18:11:20 -0700522 * @return The intent that should be set as the result for the calling activity, or
523 * <code>null</code> if the current launcher doesn't support shortcuts.
Sunny Goyala6be88a2017-01-12 16:27:58 -0800524 *
525 * @see Intent#ACTION_CREATE_SHORTCUT
526 *
527 * @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled.
528 */
529 public Intent createShortcutResultIntent(@NonNull ShortcutInfo shortcut) {
530 try {
531 return mService.createShortcutResultIntent(mContext.getPackageName(), shortcut,
532 injectMyUserId());
533 } catch (RemoteException e) {
534 throw e.rethrowFromSystemServer();
535 }
536 }
537
538 /**
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700539 * Called internally when an app is considered to have come to the foreground
Makoto Onukid6e1f3b2016-06-14 11:17:59 -0700540 * even when technically it's not. This method resets the throttling for this package.
Kevin Hufnagle68d699d2016-10-14 19:04:51 -0700541 * For example, when the user sends an "inline reply" on a notification, the system UI will
Makoto Onukid6e1f3b2016-06-14 11:17:59 -0700542 * call it.
543 *
544 * @hide
545 */
546 public void onApplicationActive(@NonNull String packageName, @UserIdInt int userId) {
547 try {
548 mService.onApplicationActive(packageName, userId);
549 } catch (RemoteException e) {
550 throw e.rethrowFromSystemServer();
551 }
552 }
553
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800554 /** @hide injection point */
555 @VisibleForTesting
556 protected int injectMyUserId() {
Jeff Sharkeyad357d12018-02-02 13:25:31 -0700557 return mContext.getUserId();
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800558 }
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -0800559
560 /**
561 * Used by framework's ShareSheet (ChooserActivity.java) to retrieve all of the direct share
562 * targets that match the given IntentFilter.
563 *
564 * @param filter IntentFilter that will be used to retrieve the matching {@link ShortcutInfo}s.
565 * @return List of {@link ShareShortcutInfo}s that match the given IntentFilter.
566 * @hide
567 */
568 @NonNull
569 @SystemApi
Sunny Goyalddd089a2019-03-21 12:45:43 -0700570 @RequiresPermission(Manifest.permission.MANAGE_APP_PREDICTIONS)
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -0800571 public List<ShareShortcutInfo> getShareTargets(@NonNull IntentFilter filter) {
572 try {
573 return mService.getShareTargets(mContext.getPackageName(), filter,
574 injectMyUserId()).getList();
575 } catch (RemoteException e) {
576 throw e.rethrowFromSystemServer();
577 }
578 }
579
580 /**
581 * Represents the result of a query return by {@link #getShareTargets(IntentFilter)}.
582 *
583 * @hide
584 */
585 @SystemApi
586 public static final class ShareShortcutInfo implements Parcelable {
587 private final ShortcutInfo mShortcutInfo;
588 private final ComponentName mTargetComponent;
589
590 /**
591 * @hide
592 */
593 public ShareShortcutInfo(@NonNull ShortcutInfo shortcutInfo,
594 @NonNull ComponentName targetComponent) {
595 if (shortcutInfo == null) {
596 throw new NullPointerException("shortcut info is null");
597 }
598 if (targetComponent == null) {
599 throw new NullPointerException("target component is null");
600 }
601
602 mShortcutInfo = shortcutInfo;
603 mTargetComponent = targetComponent;
604 }
605
Mehdi Alizadeh387c7cb2019-03-05 16:36:08 -0800606 private ShareShortcutInfo(@NonNull Parcel in) {
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -0800607 mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader());
608 mTargetComponent = in.readParcelable(ComponentName.class.getClassLoader());
609 }
610
Mehdi Alizadeh387c7cb2019-03-05 16:36:08 -0800611 @NonNull
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -0800612 public ShortcutInfo getShortcutInfo() {
613 return mShortcutInfo;
614 }
615
Mehdi Alizadeh387c7cb2019-03-05 16:36:08 -0800616 @NonNull
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -0800617 public ComponentName getTargetComponent() {
618 return mTargetComponent;
619 }
620
621 @Override
622 public int describeContents() {
623 return 0;
624 }
625
626 @Override
Mehdi Alizadeh387c7cb2019-03-05 16:36:08 -0800627 public void writeToParcel(@NonNull Parcel dest, int flags) {
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -0800628 dest.writeParcelable(mShortcutInfo, flags);
629 dest.writeParcelable(mTargetComponent, flags);
630 }
631
Mehdi Alizadeh387c7cb2019-03-05 16:36:08 -0800632 public static final @NonNull Parcelable.Creator<ShareShortcutInfo> CREATOR =
Mehdi Alizadeh406e8b32018-12-11 18:21:49 -0800633 new Parcelable.Creator<ShareShortcutInfo>() {
634 public ShareShortcutInfo createFromParcel(Parcel in) {
635 return new ShareShortcutInfo(in);
636 }
637
638 public ShareShortcutInfo[] newArray(int size) {
639 return new ShareShortcutInfo[size];
640 }
641 };
642 }
Mehdi Alizadeh85fd3d52019-01-23 12:49:53 -0800643
644 /**
645 * Used by framework's ShareSheet (ChooserActivity.java) to check if a given package has share
646 * target definitions in it's resources.
647 *
648 * @param packageName Package to check for share targets.
649 * @return True if the package has any share target definitions, False otherwise.
650 * @hide
651 */
Mehdi Alizadeh627d4db2019-02-04 13:52:03 -0800652 @SystemApi
Mehdi Alizadeh85fd3d52019-01-23 12:49:53 -0800653 public boolean hasShareTargets(@NonNull String packageName) {
654 try {
655 return mService.hasShareTargets(mContext.getPackageName(), packageName,
656 injectMyUserId());
657 } catch (RemoteException e) {
658 throw e.rethrowFromSystemServer();
659 }
660 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800661}