blob: ed958b1186500207e83571e4b5a675ca0479c6a9 [file] [log] [blame]
Amith Yamasani4f582632014-02-19 14:31:52 -08001/*
2 * Copyright (C) 2014 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
17package android.content.pm;
18
Jon Miranda2b340a22019-01-25 14:03:49 -080019import android.annotation.CallbackExecutor;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080020import android.annotation.IntDef;
21import android.annotation.NonNull;
22import android.annotation.Nullable;
Makoto Onuki2d895c32016-12-02 15:48:40 -080023import android.annotation.SdkConstant;
24import android.annotation.SdkConstant.SdkConstantType;
Sunny Goyalbeee1972019-03-29 11:38:16 -070025import android.annotation.SystemApi;
Makoto Onukib1588c02017-10-12 15:11:45 -070026import android.annotation.SystemService;
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070027import android.annotation.TestApi;
Makoto Onukia37ac3d2017-04-14 12:33:10 -070028import android.app.PendingIntent;
29import android.appwidget.AppWidgetManager;
Sunny Goyal87a563e2017-01-01 19:42:45 -080030import android.appwidget.AppWidgetProviderInfo;
Artur Satayeve23a0eb2019-12-10 17:47:52 +000031import android.compat.annotation.UnsupportedAppUsage;
Makoto Onuki83f6d2d2016-07-11 14:30:19 -070032import android.content.ActivityNotFoundException;
Amith Yamasani4f582632014-02-19 14:31:52 -080033import android.content.ComponentName;
34import android.content.Context;
35import android.content.Intent;
Sunny Goyala6be88a2017-01-12 16:27:58 -080036import android.content.IntentSender;
Jon Miranda2b340a22019-01-25 14:03:49 -080037import android.content.pm.PackageInstaller.SessionCallback;
38import android.content.pm.PackageInstaller.SessionCallbackDelegate;
39import android.content.pm.PackageInstaller.SessionInfo;
Kenny Guy77242752016-01-15 13:29:06 +000040import android.content.pm.PackageManager.ApplicationInfoFlags;
Makoto Onuki04b9aab2016-05-23 17:13:30 -070041import android.content.pm.PackageManager.NameNotFoundException;
42import android.content.res.Resources;
43import android.graphics.Bitmap;
44import android.graphics.BitmapFactory;
Amith Yamasani4f582632014-02-19 14:31:52 -080045import android.graphics.Rect;
Makoto Onukib1588c02017-10-12 15:11:45 -070046import android.graphics.drawable.AdaptiveIconDrawable;
Makoto Onuki04b9aab2016-05-23 17:13:30 -070047import android.graphics.drawable.BitmapDrawable;
Makoto Onuki20c95f82016-05-11 16:51:01 -070048import android.graphics.drawable.Drawable;
Makoto Onuki2d895c32016-12-02 15:48:40 -080049import android.graphics.drawable.Icon;
Mathew Inwood8c854f82018-09-14 12:35:36 +010050import android.os.Build;
Amith Yamasani4f582632014-02-19 14:31:52 -080051import android.os.Bundle;
Kenny Guyb42c89b2014-07-28 19:20:07 +010052import android.os.Handler;
53import android.os.Looper;
54import android.os.Message;
Makoto Onuki2d895c32016-12-02 15:48:40 -080055import android.os.Parcel;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080056import android.os.ParcelFileDescriptor;
Makoto Onuki2d895c32016-12-02 15:48:40 -080057import android.os.Parcelable;
Amith Yamasani4f582632014-02-19 14:31:52 -080058import android.os.RemoteException;
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070059import android.os.ServiceManager;
Amith Yamasani4f582632014-02-19 14:31:52 -080060import android.os.UserHandle;
Amith Yamasanie781c812014-05-28 15:28:18 -070061import android.os.UserManager;
Makoto Onuki04b9aab2016-05-23 17:13:30 -070062import android.util.DisplayMetrics;
Amith Yamasani4f582632014-02-19 14:31:52 -080063import android.util.Log;
64
Makoto Onuki04b9aab2016-05-23 17:13:30 -070065import java.io.IOException;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080066import java.lang.annotation.Retention;
67import java.lang.annotation.RetentionPolicy;
Amith Yamasani4f582632014-02-19 14:31:52 -080068import java.util.ArrayList;
Makoto Onukib6d35232016-04-04 15:57:17 -070069import java.util.Arrays;
Amith Yamasani4f582632014-02-19 14:31:52 -080070import java.util.Collections;
Jon Miranda2b340a22019-01-25 14:03:49 -080071import java.util.Iterator;
Amith Yamasani4f582632014-02-19 14:31:52 -080072import java.util.List;
Daulet Zhanguzina2044e12019-12-30 16:34:59 +000073import java.util.Objects;
Jon Miranda2b340a22019-01-25 14:03:49 -080074import java.util.concurrent.Executor;
Amith Yamasani4f582632014-02-19 14:31:52 -080075
76/**
77 * Class for retrieving a list of launchable activities for the current user and any associated
Makoto Onukiaecbd032017-01-19 12:11:11 -080078 * managed profiles that are visible to the current user, which can be retrieved with
79 * {@link #getProfiles}. This is mainly for use by launchers.
80 *
81 * Apps can be queried for each user profile.
Amith Yamasani4f582632014-02-19 14:31:52 -080082 * Since the PackageManager will not deliver package broadcasts for other profiles, you can register
83 * for package changes here.
Amith Yamasanie781c812014-05-28 15:28:18 -070084 * <p>
85 * To watch for managed profiles being added or removed, register for the following broadcasts:
86 * {@link Intent#ACTION_MANAGED_PROFILE_ADDED} and {@link Intent#ACTION_MANAGED_PROFILE_REMOVED}.
87 * <p>
Makoto Onukiaecbd032017-01-19 12:11:11 -080088 * Note as of Android O, apps on a managed profile are no longer allowed to access apps on the
89 * main profile. Apps can only access profiles returned by {@link #getProfiles()}.
Amith Yamasani4f582632014-02-19 14:31:52 -080090 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060091@SystemService(Context.LAUNCHER_APPS_SERVICE)
Amith Yamasani4f582632014-02-19 14:31:52 -080092public class LauncherApps {
93
94 static final String TAG = "LauncherApps";
95 static final boolean DEBUG = false;
96
Makoto Onuki2d895c32016-12-02 15:48:40 -080097 /**
98 * Activity Action: For the default launcher to show the confirmation dialog to create
99 * a pinned shortcut.
100 *
101 * <p>See the {@link ShortcutManager} javadoc for details.
102 *
103 * <p>
104 * Use {@link #getPinItemRequest(Intent)} to get a {@link PinItemRequest} object,
105 * and call {@link PinItemRequest#accept(Bundle)}
106 * if the user accepts. If the user doesn't accept, no further action is required.
107 *
108 * @see #EXTRA_PIN_ITEM_REQUEST
109 */
110 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
Sunny Goyal7f7372a2017-01-24 11:53:54 -0800111 public static final String ACTION_CONFIRM_PIN_SHORTCUT =
112 "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
Makoto Onuki2d895c32016-12-02 15:48:40 -0800113
114 /**
Sunny Goyal7f7372a2017-01-24 11:53:54 -0800115 * Activity Action: For the default launcher to show the confirmation dialog to create
116 * a pinned app widget.
117 *
118 * <p>See the {@link android.appwidget.AppWidgetManager#requestPinAppWidget} javadoc for
119 * details.
120 *
121 * <p>
122 * Use {@link #getPinItemRequest(Intent)} to get a {@link PinItemRequest} object,
123 * and call {@link PinItemRequest#accept(Bundle)}
124 * if the user accepts. If the user doesn't accept, no further action is required.
125 *
126 * @see #EXTRA_PIN_ITEM_REQUEST
127 */
128 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
129 public static final String ACTION_CONFIRM_PIN_APPWIDGET =
130 "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
131
132 /**
133 * An extra for {@link #ACTION_CONFIRM_PIN_SHORTCUT} &amp; {@link #ACTION_CONFIRM_PIN_APPWIDGET}
134 * containing a {@link PinItemRequest} of appropriate type asked to pin.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800135 *
136 * <p>A helper function {@link #getPinItemRequest(Intent)} can be used
137 * instead of using this constant directly.
138 *
Sunny Goyal7f7372a2017-01-24 11:53:54 -0800139 * @see #ACTION_CONFIRM_PIN_SHORTCUT
140 * @see #ACTION_CONFIRM_PIN_APPWIDGET
Makoto Onuki2d895c32016-12-02 15:48:40 -0800141 */
142 public static final String EXTRA_PIN_ITEM_REQUEST =
143 "android.content.pm.extra.PIN_ITEM_REQUEST";
144
Makoto Onukide3c16c2017-01-26 11:39:31 -0800145 private final Context mContext;
Mathew Inwood8c854f82018-09-14 12:35:36 +0100146 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Makoto Onukide3c16c2017-01-26 11:39:31 -0800147 private final ILauncherApps mService;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100148 @UnsupportedAppUsage
Makoto Onukide3c16c2017-01-26 11:39:31 -0800149 private final PackageManager mPm;
150 private final UserManager mUserManager;
Amith Yamasani4f582632014-02-19 14:31:52 -0800151
Jon Miranda2b340a22019-01-25 14:03:49 -0800152 private final List<CallbackMessageHandler> mCallbacks = new ArrayList<>();
153 private final List<SessionCallbackDelegate> mDelegates = new ArrayList<>();
Kenny Guyc01545372014-06-16 14:17:26 +0100154
155 /**
156 * Callbacks for package changes to this and related managed profiles.
157 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100158 public static abstract class Callback {
Kenny Guyc01545372014-06-16 14:17:26 +0100159 /**
160 * Indicates that a package was removed from the specified profile.
161 *
Kenny Guyb42c89b2014-07-28 19:20:07 +0100162 * If a package is removed while being updated onPackageChanged will be
163 * called instead.
164 *
Kenny Guyc01545372014-06-16 14:17:26 +0100165 * @param packageName The name of the package that was removed.
166 * @param user The UserHandle of the profile that generated the change.
167 */
168 abstract public void onPackageRemoved(String packageName, UserHandle user);
169
170 /**
171 * Indicates that a package was added to the specified profile.
172 *
Kenny Guyb42c89b2014-07-28 19:20:07 +0100173 * If a package is added while being updated then onPackageChanged will be
174 * called instead.
175 *
Kenny Guyc01545372014-06-16 14:17:26 +0100176 * @param packageName The name of the package that was added.
177 * @param user The UserHandle of the profile that generated the change.
178 */
179 abstract public void onPackageAdded(String packageName, UserHandle user);
180
181 /**
182 * Indicates that a package was modified in the specified profile.
Kenny Guyb42c89b2014-07-28 19:20:07 +0100183 * This can happen, for example, when the package is updated or when
184 * one or more components are enabled or disabled.
Kenny Guyc01545372014-06-16 14:17:26 +0100185 *
186 * @param packageName The name of the package that has changed.
187 * @param user The UserHandle of the profile that generated the change.
188 */
189 abstract public void onPackageChanged(String packageName, UserHandle user);
190
191 /**
192 * Indicates that one or more packages have become available. For
193 * example, this can happen when a removable storage card has
194 * reappeared.
195 *
196 * @param packageNames The names of the packages that have become
197 * available.
198 * @param user The UserHandle of the profile that generated the change.
199 * @param replacing Indicates whether these packages are replacing
200 * existing ones.
201 */
202 abstract public void onPackagesAvailable(String[] packageNames, UserHandle user,
203 boolean replacing);
204
205 /**
206 * Indicates that one or more packages have become unavailable. For
207 * example, this can happen when a removable storage card has been
208 * removed.
209 *
210 * @param packageNames The names of the packages that have become
211 * unavailable.
212 * @param user The UserHandle of the profile that generated the change.
213 * @param replacing Indicates whether the packages are about to be
214 * replaced with new versions.
215 */
216 abstract public void onPackagesUnavailable(String[] packageNames, UserHandle user,
217 boolean replacing);
Kenny Guy77242752016-01-15 13:29:06 +0000218
219 /**
220 * Indicates that one or more packages have been suspended. For
221 * example, this can happen when a Device Administrator suspends
222 * an applicaton.
223 *
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700224 * <p>Note: On devices running {@link android.os.Build.VERSION_CODES#P Android P} or higher,
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700225 * any apps that override {@link #onPackagesSuspended(String[], UserHandle, Bundle)} will
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700226 * not receive this callback.
227 *
Kenny Guy77242752016-01-15 13:29:06 +0000228 * @param packageNames The names of the packages that have just been
229 * suspended.
230 * @param user The UserHandle of the profile that generated the change.
231 */
232 public void onPackagesSuspended(String[] packageNames, UserHandle user) {
233 }
234
235 /**
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700236 * Indicates that one or more packages have been suspended. A device administrator or an app
237 * with {@code android.permission.SUSPEND_APPS} can do this.
238 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700239 * <p>A suspending app with the permission {@code android.permission.SUSPEND_APPS} can
240 * optionally provide a {@link Bundle} of extra information that it deems helpful for the
241 * launcher to handle the suspended state of these packages. The contents of this
Suprabh Shukla3e03ab92018-04-11 16:03:49 -0700242 * {@link Bundle} are supposed to be a contract between the suspending app and the launcher.
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700243 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700244 * @param packageNames The names of the packages that have just been suspended.
245 * @param user the user for which the given packages were suspended.
246 * @param launcherExtras A {@link Bundle} of extras for the launcher, if provided to the
247 * system, {@code null} otherwise.
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700248 * @see PackageManager#isPackageSuspended()
249 * @see #getSuspendedPackageLauncherExtras(String, UserHandle)
Suprabh Shuklad3278442019-08-27 15:58:03 -0700250 * @deprecated {@code launcherExtras} should be obtained by using
251 * {@link #getSuspendedPackageLauncherExtras(String, UserHandle)}. For all other cases,
252 * {@link #onPackagesSuspended(String[], UserHandle)} should be used.
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700253 */
Suprabh Shuklad3278442019-08-27 15:58:03 -0700254 @Deprecated
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700255 public void onPackagesSuspended(String[] packageNames, UserHandle user,
256 @Nullable Bundle launcherExtras) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700257 onPackagesSuspended(packageNames, user);
258 }
259
260 /**
Kenny Guy77242752016-01-15 13:29:06 +0000261 * Indicates that one or more packages have been unsuspended. For
262 * example, this can happen when a Device Administrator unsuspends
263 * an applicaton.
264 *
265 * @param packageNames The names of the packages that have just been
266 * unsuspended.
267 * @param user The UserHandle of the profile that generated the change.
268 */
269 public void onPackagesUnsuspended(String[] packageNames, UserHandle user) {
270 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800271
272 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700273 * Indicates that one or more shortcuts of any kind (dynamic, pinned, or manifest)
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800274 * have been added, updated or removed.
275 *
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800276 * <p>Only the applications that are allowed to access the shortcut information,
277 * as defined in {@link #hasShortcutHostPermission()}, will receive it.
278 *
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800279 * @param packageName The name of the package that has the shortcuts.
Makoto Onukife9c9662016-07-25 15:12:23 -0700280 * @param shortcuts All shortcuts from the package (dynamic, manifest and/or pinned).
281 * Only "key" information will be provided, as defined in
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700282 * {@link ShortcutInfo#hasKeyFieldsOnly()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800283 * @param user The UserHandle of the profile that generated the change.
Makoto Onuki4a910962016-07-07 13:57:34 -0700284 *
285 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800286 */
287 public void onShortcutsChanged(@NonNull String packageName,
288 @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
289 }
290 }
291
292 /**
293 * Represents a query passed to {@link #getShortcuts(ShortcutQuery, UserHandle)}.
294 */
295 public static class ShortcutQuery {
296 /**
297 * Include dynamic shortcuts in the result.
298 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700299 public static final int FLAG_MATCH_DYNAMIC = 1 << 0;
300
301 /** @hide kept for unit tests */
302 @Deprecated
303 public static final int FLAG_GET_DYNAMIC = FLAG_MATCH_DYNAMIC;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800304
305 /**
306 * Include pinned shortcuts in the result.
Makoto Onuki88b4dcc2017-12-07 15:53:56 -0800307 *
308 * <p>If you are the selected assistant app, and wishes to fetch all shortcuts that the
309 * user owns on the launcher (or by other launchers, in case the user has multiple), use
310 * {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} instead.
311 *
312 * <p>If you're a regular launcher app, there's no way to get shortcuts pinned by other
313 * launchers, and {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} will be ignored. So use this
314 * flag to get own pinned shortcuts.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800315 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700316 public static final int FLAG_MATCH_PINNED = 1 << 1;
317
318 /** @hide kept for unit tests */
319 @Deprecated
320 public static final int FLAG_GET_PINNED = FLAG_MATCH_PINNED;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800321
322 /**
Makoto Onuki22fcc682016-05-17 14:52:19 -0700323 * Include manifest shortcuts in the result.
324 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700325 public static final int FLAG_MATCH_MANIFEST = 1 << 3;
326
327 /** @hide kept for unit tests */
328 @Deprecated
329 public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700330
Hakan Seyalioglu58fc95d2016-12-13 15:23:22 -0800331 /**
Makoto Onuki35559d62017-11-06 16:26:32 -0800332 * Include all pinned shortcuts by any launchers, not just by the caller,
Makoto Onuki634cecb2017-10-13 17:10:48 -0700333 * in the result.
Makoto Onuki35559d62017-11-06 16:26:32 -0800334 *
Makoto Onuki88b4dcc2017-12-07 15:53:56 -0800335 * <p>The caller must be the selected assistant app to use this flag, or have the system
Makoto Onuki35559d62017-11-06 16:26:32 -0800336 * {@code ACCESS_SHORTCUTS} permission.
Makoto Onuki88b4dcc2017-12-07 15:53:56 -0800337 *
338 * <p>If you are the selected assistant app, and wishes to fetch all shortcuts that the
339 * user owns on the launcher (or by other launchers, in case the user has multiple), use
340 * {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} instead.
341 *
342 * <p>If you're a regular launcher app (or any app that's not the selected assistant app)
343 * then this flag will be ignored.
Makoto Onuki634cecb2017-10-13 17:10:48 -0700344 */
Makoto Onuki35559d62017-11-06 16:26:32 -0800345 public static final int FLAG_MATCH_PINNED_BY_ANY_LAUNCHER = 1 << 10;
Makoto Onuki634cecb2017-10-13 17:10:48 -0700346
347 /**
348 * FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST
Hakan Seyalioglu58fc95d2016-12-13 15:23:22 -0800349 * @hide
350 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700351 public static final int FLAG_MATCH_ALL_KINDS =
Makoto Onuki634cecb2017-10-13 17:10:48 -0700352 FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST;
353
354 /**
355 * FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST | FLAG_MATCH_ALL_PINNED
356 * @hide
357 */
358 public static final int FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED =
Makoto Onuki35559d62017-11-06 16:26:32 -0800359 FLAG_MATCH_ALL_KINDS | FLAG_MATCH_PINNED_BY_ANY_LAUNCHER;
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700360
Makoto Onukib5a012f2016-06-21 11:13:53 -0700361 /** @hide kept for unit tests */
362 @Deprecated
363 public static final int FLAG_GET_ALL_KINDS = FLAG_MATCH_ALL_KINDS;
364
Makoto Onuki22fcc682016-05-17 14:52:19 -0700365 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700366 * Requests "key" fields only. See {@link ShortcutInfo#hasKeyFieldsOnly()}'s javadoc to
367 * see which fields fields "key".
368 * This allows quicker access to shortcut information in order to
369 * determine whether the caller's in-memory cache needs to be updated.
Makoto Onuki4a910962016-07-07 13:57:34 -0700370 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700371 * <p>Typically, launcher applications cache all or most shortcut information
372 * in memory in order to show shortcuts without a delay.
373 *
374 * When a given launcher application wants to update its cache, such as when its process
375 * restarts, it can fetch shortcut information with this flag.
376 * The application can then check {@link ShortcutInfo#getLastChangedTimestamp()} for each
377 * shortcut, fetching a shortcut's non-key information only if that shortcut has been
378 * updated.
Makoto Onuki4a910962016-07-07 13:57:34 -0700379 *
380 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800381 */
382 public static final int FLAG_GET_KEY_FIELDS_ONLY = 1 << 2;
383
384 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700385 @IntDef(flag = true, prefix = { "FLAG_" }, value = {
386 FLAG_MATCH_DYNAMIC,
387 FLAG_MATCH_PINNED,
388 FLAG_MATCH_MANIFEST,
389 FLAG_GET_KEY_FIELDS_ONLY,
390 FLAG_MATCH_MANIFEST,
391 })
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800392 @Retention(RetentionPolicy.SOURCE)
393 public @interface QueryFlags {}
394
395 long mChangedSince;
396
397 @Nullable
398 String mPackage;
399
400 @Nullable
Makoto Onukiabe84422016-04-07 09:41:19 -0700401 List<String> mShortcutIds;
402
403 @Nullable
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800404 ComponentName mActivity;
405
406 @QueryFlags
407 int mQueryFlags;
408
409 public ShortcutQuery() {
410 }
411
412 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700413 * If non-zero, returns only shortcuts that have been added or updated
414 * since the given timestamp, expressed in milliseconds since the Epoch&mdash;see
415 * {@link System#currentTimeMillis()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800416 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700417 public ShortcutQuery setChangedSince(long changedSince) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800418 mChangedSince = changedSince;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700419 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800420 }
421
422 /**
423 * If non-null, returns only shortcuts from the package.
424 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700425 public ShortcutQuery setPackage(@Nullable String packageName) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800426 mPackage = packageName;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700427 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800428 }
429
430 /**
Makoto Onukiabe84422016-04-07 09:41:19 -0700431 * If non-null, return only the specified shortcuts by ID. When setting this field,
Makoto Onuki4a910962016-07-07 13:57:34 -0700432 * a package name must also be set with {@link #setPackage}.
Makoto Onukiabe84422016-04-07 09:41:19 -0700433 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700434 public ShortcutQuery setShortcutIds(@Nullable List<String> shortcutIds) {
Makoto Onukiabe84422016-04-07 09:41:19 -0700435 mShortcutIds = shortcutIds;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700436 return this;
Makoto Onukiabe84422016-04-07 09:41:19 -0700437 }
438
439 /**
Makoto Onuki22fcc682016-05-17 14:52:19 -0700440 * If non-null, returns only shortcuts associated with the activity; i.e.
441 * {@link ShortcutInfo}s whose {@link ShortcutInfo#getActivity()} are equal
442 * to {@code activity}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800443 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700444 public ShortcutQuery setActivity(@Nullable ComponentName activity) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800445 mActivity = activity;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700446 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800447 }
448
Hakan Seyalioglu58fc95d2016-12-13 15:23:22 -0800449 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700450 * Set query options. At least one of the {@code MATCH} flags should be set. Otherwise,
451 * no shortcuts will be returned.
Makoto Onuki4a910962016-07-07 13:57:34 -0700452 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700453 * <ul>
454 * <li>{@link #FLAG_MATCH_DYNAMIC}
455 * <li>{@link #FLAG_MATCH_PINNED}
456 * <li>{@link #FLAG_MATCH_MANIFEST}
457 * <li>{@link #FLAG_GET_KEY_FIELDS_ONLY}
458 * </ul>
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800459 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700460 public ShortcutQuery setQueryFlags(@QueryFlags int queryFlags) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800461 mQueryFlags = queryFlags;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700462 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800463 }
Kenny Guyc01545372014-06-16 14:17:26 +0100464 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800465
Amith Yamasani4f582632014-02-19 14:31:52 -0800466 /** @hide */
467 public LauncherApps(Context context, ILauncherApps service) {
468 mContext = context;
469 mService = service;
Amith Yamasanie781c812014-05-28 15:28:18 -0700470 mPm = context.getPackageManager();
Makoto Onukide3c16c2017-01-26 11:39:31 -0800471 mUserManager = context.getSystemService(UserManager.class);
Amith Yamasani4f582632014-02-19 14:31:52 -0800472 }
473
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -0700474 /** @hide */
475 @TestApi
476 public LauncherApps(Context context) {
477 this(context, ILauncherApps.Stub.asInterface(
478 ServiceManager.getService(Context.LAUNCHER_APPS_SERVICE)));
479 }
480
Amith Yamasani4f582632014-02-19 14:31:52 -0800481 /**
Makoto Onukide3c16c2017-01-26 11:39:31 -0800482 * Show an error log on logcat, when the calling user is a managed profile, and the target
483 * user is different from the calling user, in order to help developers to detect it.
484 */
485 private void logErrorForInvalidProfileAccess(@NonNull UserHandle target) {
486 if (UserHandle.myUserId() != target.getIdentifier() && mUserManager.isManagedProfile()) {
Makoto Onuki3cc7cd12017-04-03 12:48:42 -0700487 Log.w(TAG, "Accessing other profiles/users from managed profile is no longer allowed.");
Makoto Onukide3c16c2017-01-26 11:39:31 -0800488 }
489 }
490
491 /**
Makoto Onukiaecbd032017-01-19 12:11:11 -0800492 * Return a list of profiles that the caller can access via the {@link LauncherApps} APIs.
493 *
494 * <p>If the caller is running on a managed profile, it'll return only the current profile.
495 * Otherwise it'll return the same list as {@link UserManager#getUserProfiles()} would.
496 */
497 public List<UserHandle> getProfiles() {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800498 if (mUserManager.isManagedProfile()) {
Makoto Onukiaecbd032017-01-19 12:11:11 -0800499 // If it's a managed profile, only return the current profile.
500 final List result = new ArrayList(1);
501 result.add(android.os.Process.myUserHandle());
502 return result;
503 } else {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800504 return mUserManager.getUserProfiles();
Makoto Onukiaecbd032017-01-19 12:11:11 -0800505 }
506 }
507
508 /**
Kevin Hufnagle25266af2019-08-14 17:23:58 -0700509 * Retrieves a list of activities that specify {@link Intent#ACTION_MAIN} and
510 * {@link Intent#CATEGORY_LAUNCHER}, across all apps, for a specified user. If an app doesn't
511 * have any activities that specify <code>ACTION_MAIN</code> or <code>CATEGORY_LAUNCHER</code>,
512 * the system adds a synthesized activity to the list. This synthesized activity represents the
513 * app's details page within system settings.
514 *
515 * <p class="note"><b>Note: </b>It's possible for system apps, such as app stores, to prevent
516 * the system from adding synthesized activities to the returned list.</p>
517 *
518 * <p>As of <a href="/reference/android/os/Build.VERSION_CODES.html#Q">Android Q</a>, at least
519 * one of the app's activities or synthesized activities appears in the returned list unless the
520 * app satisfies at least one of the following conditions:</p>
521 * <ul>
522 * <li>The app is a system app.</li>
523 * <li>The app doesn't request any <a href="/guide/topics/permissions/overview">permissions</a>.
524 * </li>
Kevin Hufnagleb8779b82019-09-13 02:18:44 +0000525 * <li>The app doesn't have a <em>launcher activity</em> that is enabled by default. A launcher
526 * activity has an intent containing the <code>ACTION_MAIN</code> action and the
527 * <code>CATEGORY_LAUNCHER</code> category.</li>
Kevin Hufnagle25266af2019-08-14 17:23:58 -0700528 * </ul>
529 *
530 * <p>Additionally, the system hides synthesized activities for some or all apps in the
531 * following enterprise-related cases:</p>
532 * <ul>
533 * <li>If the device is a
534 * <a href="https://developers.google.com/android/work/overview#company-owned-devices-for-knowledge-workers">fully
535 * managed device</a>, no synthesized activities for any app appear in the returned list.</li>
536 * <li>If the current user has a
537 * <a href="https://developers.google.com/android/work/overview#employee-owned-devices-byod">work
538 * profile</a>, no synthesized activities for the user's work apps appear in the returned
539 * list.</li>
540 * </ul>
Amith Yamasani4f582632014-02-19 14:31:52 -0800541 *
542 * @param packageName The specific package to query. If null, it checks all installed packages
543 * in the profile.
544 * @param user The UserHandle of the profile.
545 * @return List of launchable activities. Can be an empty list but will not be null.
546 */
547 public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800548 logErrorForInvalidProfileAccess(user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800549 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800550 return convertToActivityList(mService.getLauncherActivities(mContext.getPackageName(),
551 packageName, user), user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800552 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700553 throw re.rethrowFromSystemServer();
Amith Yamasani4f582632014-02-19 14:31:52 -0800554 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800555 }
556
Amith Yamasani4f582632014-02-19 14:31:52 -0800557 /**
558 * Returns the activity info for a given intent and user handle, if it resolves. Otherwise it
559 * returns null.
560 *
561 * @param intent The intent to find a match for.
562 * @param user The profile to look in for a match.
563 * @return An activity info object if there is a match.
564 */
565 public LauncherActivityInfo resolveActivity(Intent intent, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800566 logErrorForInvalidProfileAccess(user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800567 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800568 ActivityInfo ai = mService.resolveActivity(mContext.getPackageName(),
569 intent.getComponent(), user);
Sunny Goyal45d3e972016-03-31 12:38:17 -0700570 if (ai != null) {
571 LauncherActivityInfo info = new LauncherActivityInfo(mContext, ai, user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800572 return info;
573 }
574 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700575 throw re.rethrowFromSystemServer();
Amith Yamasani4f582632014-02-19 14:31:52 -0800576 }
577 return null;
578 }
579
580 /**
Kenny Guyf939dba2014-08-15 15:32:34 +0100581 * Starts a Main activity in the specified profile.
Amith Yamasani4f582632014-02-19 14:31:52 -0800582 *
583 * @param component The ComponentName of the activity to launch
Amith Yamasanie781c812014-05-28 15:28:18 -0700584 * @param user The UserHandle of the profile
585 * @param sourceBounds The Rect containing the source bounds of the clicked icon
586 * @param opts Options to pass to startActivity
587 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100588 public void startMainActivity(ComponentName component, UserHandle user, Rect sourceBounds,
Amith Yamasanie781c812014-05-28 15:28:18 -0700589 Bundle opts) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800590 logErrorForInvalidProfileAccess(user);
Amith Yamasani5abdbb62014-04-08 17:23:46 -0700591 if (DEBUG) {
Kenny Guyf939dba2014-08-15 15:32:34 +0100592 Log.i(TAG, "StartMainActivity " + component + " " + user.getIdentifier());
Amith Yamasani5abdbb62014-04-08 17:23:46 -0700593 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800594 try {
Makoto Onuki1a342742018-04-26 14:56:59 -0700595 mService.startActivityAsUser(mContext.getIApplicationThread(),
596 mContext.getPackageName(),
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800597 component, sourceBounds, opts, user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800598 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700599 throw re.rethrowFromSystemServer();
Amith Yamasani4f582632014-02-19 14:31:52 -0800600 }
601 }
602
603 /**
Jon Miranda2b340a22019-01-25 14:03:49 -0800604 * Starts an activity to show the details of the specified session.
605 *
606 * @param sessionInfo The SessionInfo of the session
607 * @param sourceBounds The Rect containing the source bounds of the clicked icon
608 * @param opts Options to pass to startActivity
609 */
Jon Miranda93505982019-03-08 09:33:42 -0800610 public void startPackageInstallerSessionDetailsActivity(@NonNull SessionInfo sessionInfo,
611 @Nullable Rect sourceBounds, @Nullable Bundle opts) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800612 try {
613 mService.startSessionDetailsActivityAsUser(mContext.getIApplicationThread(),
614 mContext.getPackageName(), sessionInfo, sourceBounds, opts,
615 sessionInfo.getUser());
616 } catch (RemoteException re) {
617 throw re.rethrowFromSystemServer();
618 }
619 }
620
621 /**
Kenny Guy466d2032014-07-23 12:23:35 +0100622 * Starts the settings activity to show the application details for a
623 * package in the specified profile.
624 *
625 * @param component The ComponentName of the package to launch settings for.
626 * @param user The UserHandle of the profile
627 * @param sourceBounds The Rect containing the source bounds of the clicked icon
628 * @param opts Options to pass to startActivity
629 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100630 public void startAppDetailsActivity(ComponentName component, UserHandle user,
Kenny Guy466d2032014-07-23 12:23:35 +0100631 Rect sourceBounds, Bundle opts) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800632 logErrorForInvalidProfileAccess(user);
Kenny Guy466d2032014-07-23 12:23:35 +0100633 try {
Makoto Onuki1a342742018-04-26 14:56:59 -0700634 mService.showAppDetailsAsUser(mContext.getIApplicationThread(),
635 mContext.getPackageName(),
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800636 component, sourceBounds, opts, user);
Kenny Guy466d2032014-07-23 12:23:35 +0100637 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700638 throw re.rethrowFromSystemServer();
Kenny Guy466d2032014-07-23 12:23:35 +0100639 }
640 }
641
642 /**
Sunny Goyala6be88a2017-01-12 16:27:58 -0800643 * Retrieves a list of config activities for creating {@link ShortcutInfo}.
644 *
645 * @param packageName The specific package to query. If null, it checks all installed packages
646 * in the profile.
647 * @param user The UserHandle of the profile.
648 * @return List of config activities. Can be an empty list but will not be null.
649 *
650 * @see Intent#ACTION_CREATE_SHORTCUT
651 * @see #getShortcutConfigActivityIntent(LauncherActivityInfo)
652 */
653 public List<LauncherActivityInfo> getShortcutConfigActivityList(@Nullable String packageName,
654 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800655 logErrorForInvalidProfileAccess(user);
Sunny Goyala6be88a2017-01-12 16:27:58 -0800656 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800657 return convertToActivityList(mService.getShortcutConfigActivities(
658 mContext.getPackageName(), packageName, user),
Sunny Goyala6be88a2017-01-12 16:27:58 -0800659 user);
660 } catch (RemoteException re) {
661 throw re.rethrowFromSystemServer();
662 }
663 }
664
665 private List<LauncherActivityInfo> convertToActivityList(
666 @Nullable ParceledListSlice<ResolveInfo> activities, UserHandle user) {
667 if (activities == null) {
668 return Collections.EMPTY_LIST;
669 }
670 ArrayList<LauncherActivityInfo> lais = new ArrayList<>();
671 for (ResolveInfo ri : activities.getList()) {
672 LauncherActivityInfo lai = new LauncherActivityInfo(mContext, ri.activityInfo, user);
673 if (DEBUG) {
674 Log.v(TAG, "Returning activity for profile " + user + " : "
675 + lai.getComponentName());
676 }
677 lais.add(lai);
678 }
679 return lais;
680 }
681
682 /**
683 * Returns an intent sender which can be used to start the configure activity for creating
684 * custom shortcuts. Use this method if the provider is in another profile as you are not
685 * allowed to start an activity in another profile.
686 *
687 * <p>The caller should receive {@link PinItemRequest} in onActivityResult on
688 * {@link android.app.Activity#RESULT_OK}.
689 *
690 * <p>Callers must be allowed to access the shortcut information, as defined in {@link
691 * #hasShortcutHostPermission()}.
692 *
693 * @param info a configuration activity returned by {@link #getShortcutConfigActivityList}
694 *
695 * @throws IllegalStateException when the user is locked or not running.
696 * @throws SecurityException if {@link #hasShortcutHostPermission()} is false.
697 *
698 * @see #getPinItemRequest(Intent)
699 * @see Intent#ACTION_CREATE_SHORTCUT
700 * @see android.app.Activity#startIntentSenderForResult
701 */
Makoto Onukide3c16c2017-01-26 11:39:31 -0800702 @Nullable
Sunny Goyala6be88a2017-01-12 16:27:58 -0800703 public IntentSender getShortcutConfigActivityIntent(@NonNull LauncherActivityInfo info) {
704 try {
705 return mService.getShortcutConfigActivityIntent(
706 mContext.getPackageName(), info.getComponentName(), info.getUser());
707 } catch (RemoteException re) {
708 throw re.rethrowFromSystemServer();
709 }
710 }
711
712 /**
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100713 * Checks if the package is installed and enabled for a profile.
714 *
715 * @param packageName The package to check.
716 * @param user The UserHandle of the profile.
717 *
718 * @return true if the package exists and is enabled.
719 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100720 public boolean isPackageEnabled(String packageName, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800721 logErrorForInvalidProfileAccess(user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100722 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800723 return mService.isPackageEnabled(mContext.getPackageName(), packageName, user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100724 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700725 throw re.rethrowFromSystemServer();
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100726 }
727 }
728
729 /**
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700730 * Gets the launcher extras supplied to the system when the given package was suspended via
731 * {@code PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
732 * PersistableBundle, String)}.
733 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700734 * <p>The contents of this {@link Bundle} are supposed to be a contract between the suspending
735 * app and the launcher.
736 *
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700737 * <p>Note: This just returns whatever extras were provided to the system, <em>which might
738 * even be {@code null}.</em>
739 *
740 * @param packageName The package for which to fetch the launcher extras.
741 * @param user The {@link UserHandle} of the profile.
742 * @return A {@link Bundle} of launcher extras. Or {@code null} if the package is not currently
743 * suspended.
744 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700745 * @see Callback#onPackagesSuspended(String[], UserHandle, Bundle)
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700746 * @see PackageManager#isPackageSuspended()
747 */
748 public @Nullable Bundle getSuspendedPackageLauncherExtras(String packageName, UserHandle user) {
749 logErrorForInvalidProfileAccess(user);
750 try {
751 return mService.getSuspendedPackageLauncherExtras(packageName, user);
752 } catch (RemoteException re) {
753 throw re.rethrowFromSystemServer();
754 }
755 }
756
757 /**
Suprabh Shukla79000492018-12-24 17:03:02 -0800758 * Returns whether a package should be hidden from suggestions to the user. Currently, this
759 * could be done because the package was marked as distracting to the user via
760 * {@code PackageManager.setDistractingPackageRestrictions(String[], int)}.
761 *
762 * @param packageName The package for which to check.
763 * @param user the {@link UserHandle} of the profile.
764 * @return
765 */
766 public boolean shouldHideFromSuggestions(@NonNull String packageName,
767 @NonNull UserHandle user) {
Daulet Zhanguzina2044e12019-12-30 16:34:59 +0000768 Objects.requireNonNull(packageName, "packageName");
769 Objects.requireNonNull(user, "user");
Suprabh Shukla79000492018-12-24 17:03:02 -0800770 try {
771 return mService.shouldHideFromSuggestions(packageName, user);
772 } catch (RemoteException re) {
773 throw re.rethrowFromSystemServer();
774 }
775 }
776
777 /**
Benjamin Miller7afa84c2017-07-17 13:01:35 +0200778 * Returns {@link ApplicationInfo} about an application installed for a specific user profile.
Kenny Guy77242752016-01-15 13:29:06 +0000779 *
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700780 * @param packageName The package name of the application
Kenny Guy77242752016-01-15 13:29:06 +0000781 * @param flags Additional option flags {@link PackageManager#getApplicationInfo}
782 * @param user The UserHandle of the profile.
783 *
Benjamin Miller7afa84c2017-07-17 13:01:35 +0200784 * @return {@link ApplicationInfo} containing information about the package. Returns
785 * {@code null} if the package isn't installed for the given profile, or the profile
786 * isn't enabled.
Kenny Guy77242752016-01-15 13:29:06 +0000787 */
Makoto Onuki7c7fbf62017-04-14 11:03:56 -0700788 public ApplicationInfo getApplicationInfo(@NonNull String packageName,
789 @ApplicationInfoFlags int flags, @NonNull UserHandle user)
790 throws PackageManager.NameNotFoundException {
Daulet Zhanguzina2044e12019-12-30 16:34:59 +0000791 Objects.requireNonNull(packageName, "packageName");
792 Objects.requireNonNull(user, "user");
Makoto Onukide3c16c2017-01-26 11:39:31 -0800793 logErrorForInvalidProfileAccess(user);
Kenny Guy77242752016-01-15 13:29:06 +0000794 try {
Makoto Onuki7c7fbf62017-04-14 11:03:56 -0700795 final ApplicationInfo ai = mService
796 .getApplicationInfo(mContext.getPackageName(), packageName, flags, user);
797 if (ai == null) {
798 throw new NameNotFoundException("Package " + packageName + " not found for user "
799 + user.getIdentifier());
800 }
801 return ai;
Kenny Guy77242752016-01-15 13:29:06 +0000802 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700803 throw re.rethrowFromSystemServer();
Kenny Guy77242752016-01-15 13:29:06 +0000804 }
805 }
806
807 /**
Varun Shah2546cef2019-01-11 15:50:54 -0800808 * Returns an object describing the app usage limit for the given package.
809 * If there are multiple limits that apply to the package, the one with the smallest
810 * time remaining will be returned.
811 *
812 * @param packageName name of the package whose app usage limit will be returned
813 * @param user the user of the package
814 *
815 * @return an {@link AppUsageLimit} object describing the app time limit containing
816 * the given package with the smallest time remaining, or {@code null} if none exist.
Varun Shahe9abb752019-02-11 11:25:06 -0800817 * @throws SecurityException when the caller is not the recents app.
Sunny Goyalbeee1972019-03-29 11:38:16 -0700818 * @hide
Varun Shah2546cef2019-01-11 15:50:54 -0800819 */
820 @Nullable
Sunny Goyalbeee1972019-03-29 11:38:16 -0700821 @SystemApi
Varun Shah2c9263c2019-02-15 10:51:10 -0800822 public LauncherApps.AppUsageLimit getAppUsageLimit(@NonNull String packageName,
823 @NonNull UserHandle user) {
Varun Shah2546cef2019-01-11 15:50:54 -0800824 try {
825 return mService.getAppUsageLimit(mContext.getPackageName(), packageName, user);
826 } catch (RemoteException re) {
827 throw re.rethrowFromSystemServer();
828 }
829 }
830
831 /**
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100832 * Checks if the activity exists and it enabled for a profile.
833 *
Makoto Onuki516020a2019-01-28 14:16:42 -0800834 * <p>The activity may still not be exported, in which case {@link #startMainActivity} will
835 * throw a {@link SecurityException} unless the caller has the same UID as the target app's.
836 *
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100837 * @param component The activity to check.
838 * @param user The UserHandle of the profile.
839 *
840 * @return true if the activity exists and is enabled.
841 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100842 public boolean isActivityEnabled(ComponentName component, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800843 logErrorForInvalidProfileAccess(user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100844 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800845 return mService.isActivityEnabled(mContext.getPackageName(), component, user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100846 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700847 throw re.rethrowFromSystemServer();
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100848 }
849 }
850
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800851 /**
Dianne Hackbornc160fa42017-11-01 16:14:26 -0700852 * Returns whether the caller can access the shortcut information. Access is currently
853 * available to:
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800854 *
Dianne Hackbornc160fa42017-11-01 16:14:26 -0700855 * <ul>
856 * <li>The current launcher (or default launcher if there is no set current launcher).</li>
857 * <li>The currently active voice interaction service.</li>
858 * </ul>
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800859 *
Makoto Onuki4a910962016-07-07 13:57:34 -0700860 * <p>Note when this method returns {@code false}, it may be a temporary situation because
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800861 * the user is trying a new launcher application. The user may decide to change the default
Makoto Onuki4a910962016-07-07 13:57:34 -0700862 * launcher back to the calling application again, so even if a launcher application loses
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800863 * this permission, it does <b>not</b> have to purge pinned shortcut information.
Makoto Onukife9c9662016-07-25 15:12:23 -0700864 * If the calling launcher application contains pinned shortcuts, they will still work,
865 * even though the caller no longer has the shortcut host permission.
Makoto Onuki4a910962016-07-07 13:57:34 -0700866 *
Makoto Onuki02f338e2016-07-29 09:40:40 -0700867 * @throws IllegalStateException when the user is locked.
Makoto Onuki9c850012016-07-26 15:50:50 -0700868 *
Makoto Onuki4a910962016-07-07 13:57:34 -0700869 * @see ShortcutManager
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800870 */
871 public boolean hasShortcutHostPermission() {
872 try {
873 return mService.hasShortcutHostPermission(mContext.getPackageName());
874 } catch (RemoteException re) {
875 throw re.rethrowFromSystemServer();
876 }
877 }
878
Makoto Onukib1588c02017-10-12 15:11:45 -0700879 private List<ShortcutInfo> maybeUpdateDisabledMessage(List<ShortcutInfo> shortcuts) {
880 if (shortcuts == null) {
881 return null;
882 }
883 for (int i = shortcuts.size() - 1; i >= 0; i--) {
884 final ShortcutInfo si = shortcuts.get(i);
885 final String message = ShortcutInfo.getDisabledReasonForRestoreIssue(mContext,
886 si.getDisabledReason());
887 if (message != null) {
888 si.setDisabledMessage(message);
889 }
890 }
891 return shortcuts;
892 }
893
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800894 /**
Makoto Onuki4a910962016-07-07 13:57:34 -0700895 * Returns {@link ShortcutInfo}s that match {@code query}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800896 *
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800897 * <p>Callers must be allowed to access the shortcut information, as defined in {@link
898 * #hasShortcutHostPermission()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800899 *
900 * @param query result includes shortcuts matching this query.
901 * @param user The UserHandle of the profile.
902 *
903 * @return the IDs of {@link ShortcutInfo}s that match the query.
Makoto Onuki02f338e2016-07-29 09:40:40 -0700904 * @throws IllegalStateException when the user is locked, or when the {@code user} user
905 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -0700906 *
907 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800908 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800909 @Nullable
910 public List<ShortcutInfo> getShortcuts(@NonNull ShortcutQuery query,
911 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800912 logErrorForInvalidProfileAccess(user);
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800913 try {
Makoto Onukib1588c02017-10-12 15:11:45 -0700914 // Note this is the only case we need to update the disabled message for shortcuts
915 // that weren't restored.
916 // The restore problem messages are only shown by the user, and publishers will never
917 // see them. The only other API that the launcher gets shortcuts is the shortcut
918 // changed callback, but that only returns shortcuts with the "key" information, so
919 // that won't return disabled message.
920 return maybeUpdateDisabledMessage(mService.getShortcuts(mContext.getPackageName(),
Makoto Onukiabe84422016-04-07 09:41:19 -0700921 query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
Makoto Onuki99302b52017-03-29 12:42:26 -0700922 query.mQueryFlags, user)
Makoto Onukib1588c02017-10-12 15:11:45 -0700923 .getList());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800924 } catch (RemoteException e) {
925 throw e.rethrowFromSystemServer();
926 }
927 }
928
929 /**
Makoto Onukiabe84422016-04-07 09:41:19 -0700930 * @hide // No longer used. Use getShortcuts() instead. Kept for unit tests.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800931 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800932 @Nullable
Makoto Onukib5a012f2016-06-21 11:13:53 -0700933 @Deprecated
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800934 public List<ShortcutInfo> getShortcutInfo(@NonNull String packageName,
935 @NonNull List<String> ids, @NonNull UserHandle user) {
Makoto Onukiabe84422016-04-07 09:41:19 -0700936 final ShortcutQuery q = new ShortcutQuery();
937 q.setPackage(packageName);
938 q.setShortcutIds(ids);
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700939 q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
Makoto Onukiabe84422016-04-07 09:41:19 -0700940 return getShortcuts(q, user);
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800941 }
942
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800943 /**
944 * Pin shortcuts on a package.
945 *
946 * <p>This API is <b>NOT</b> cumulative; this will replace all pinned shortcuts for the package.
947 * However, different launchers may have different set of pinned shortcuts.
948 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700949 * <p>The calling launcher application must be allowed to access the shortcut information,
950 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800951 *
952 * @param packageName The target package name.
953 * @param shortcutIds The IDs of the shortcut to be pinned.
954 * @param user The UserHandle of the profile.
Makoto Onuki02f338e2016-07-29 09:40:40 -0700955 * @throws IllegalStateException when the user is locked, or when the {@code user} user
956 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -0700957 *
958 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800959 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800960 public void pinShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
961 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800962 logErrorForInvalidProfileAccess(user);
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800963 try {
964 mService.pinShortcuts(mContext.getPackageName(), packageName, shortcutIds, user);
965 } catch (RemoteException e) {
966 throw e.rethrowFromSystemServer();
967 }
968 }
969
970 /**
Makoto Onukib6d35232016-04-04 15:57:17 -0700971 * @hide kept for testing.
Makoto Onukiabe84422016-04-07 09:41:19 -0700972 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700973 @Deprecated
Makoto Onukiabe84422016-04-07 09:41:19 -0700974 public int getShortcutIconResId(@NonNull ShortcutInfo shortcut) {
Makoto Onukib6d35232016-04-04 15:57:17 -0700975 return shortcut.getIconResourceId();
Makoto Onukiabe84422016-04-07 09:41:19 -0700976 }
977
978 /**
Makoto Onukib6d35232016-04-04 15:57:17 -0700979 * @hide kept for testing.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800980 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700981 @Deprecated
Makoto Onukiabe84422016-04-07 09:41:19 -0700982 public int getShortcutIconResId(@NonNull String packageName, @NonNull String shortcutId,
983 @NonNull UserHandle user) {
Makoto Onukib6d35232016-04-04 15:57:17 -0700984 final ShortcutQuery q = new ShortcutQuery();
985 q.setPackage(packageName);
986 q.setShortcutIds(Arrays.asList(shortcutId));
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700987 q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
Makoto Onukib6d35232016-04-04 15:57:17 -0700988 final List<ShortcutInfo> shortcuts = getShortcuts(q, user);
Makoto Onukiabe84422016-04-07 09:41:19 -0700989
Makoto Onukib6d35232016-04-04 15:57:17 -0700990 return shortcuts.size() > 0 ? shortcuts.get(0).getIconResourceId() : 0;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800991 }
992
993 /**
Makoto Onukib5a012f2016-06-21 11:13:53 -0700994 * @hide internal/unit tests only
Makoto Onukiabe84422016-04-07 09:41:19 -0700995 */
996 public ParcelFileDescriptor getShortcutIconFd(
997 @NonNull ShortcutInfo shortcut) {
Makoto Onuki22fcc682016-05-17 14:52:19 -0700998 return getShortcutIconFd(shortcut.getPackage(), shortcut.getId(),
Makoto Onukiabe84422016-04-07 09:41:19 -0700999 shortcut.getUserId());
1000 }
1001
1002 /**
Makoto Onukib5a012f2016-06-21 11:13:53 -07001003 * @hide internal/unit tests only
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001004 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001005 public ParcelFileDescriptor getShortcutIconFd(
Makoto Onukiabe84422016-04-07 09:41:19 -07001006 @NonNull String packageName, @NonNull String shortcutId, @NonNull UserHandle user) {
1007 return getShortcutIconFd(packageName, shortcutId, user.getIdentifier());
1008 }
1009
1010 private ParcelFileDescriptor getShortcutIconFd(
1011 @NonNull String packageName, @NonNull String shortcutId, int userId) {
Makoto Onuki55046222016-03-08 10:49:47 -08001012 try {
Makoto Onukiabe84422016-04-07 09:41:19 -07001013 return mService.getShortcutIconFd(mContext.getPackageName(),
1014 packageName, shortcutId, userId);
Makoto Onuki55046222016-03-08 10:49:47 -08001015 } catch (RemoteException e) {
1016 throw e.rethrowFromSystemServer();
1017 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001018 }
1019
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001020 /**
1021 * Returns the icon for this shortcut, without any badging for the profile.
1022 *
Makoto Onukife9c9662016-07-25 15:12:23 -07001023 * <p>The calling launcher application must be allowed to access the shortcut information,
1024 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki4a910962016-07-07 13:57:34 -07001025 *
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001026 * @param density The preferred density of the icon, zero for default density. Use
1027 * density DPI values from {@link DisplayMetrics}.
Makoto Onuki4a910962016-07-07 13:57:34 -07001028 *
1029 * @return The drawable associated with the shortcut.
Makoto Onuki02f338e2016-07-29 09:40:40 -07001030 * @throws IllegalStateException when the user is locked, or when the {@code user} user
1031 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -07001032 *
1033 * @see ShortcutManager
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001034 * @see #getShortcutBadgedIconDrawable(ShortcutInfo, int)
1035 * @see DisplayMetrics
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001036 */
1037 public Drawable getShortcutIconDrawable(@NonNull ShortcutInfo shortcut, int density) {
1038 if (shortcut.hasIconFile()) {
1039 final ParcelFileDescriptor pfd = getShortcutIconFd(shortcut);
1040 if (pfd == null) {
1041 return null;
1042 }
1043 try {
1044 final Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
Hyunyoung Songf281e7a2017-02-13 10:57:42 -08001045 if (bmp != null) {
1046 BitmapDrawable dr = new BitmapDrawable(mContext.getResources(), bmp);
Hyunyoung Songe4179e22017-03-01 12:51:26 -08001047 if (shortcut.hasAdaptiveBitmap()) {
Hyunyoung Songbe8835e2017-02-17 11:25:08 -08001048 return new AdaptiveIconDrawable(null, dr);
Hyunyoung Songf281e7a2017-02-13 10:57:42 -08001049 } else {
1050 return dr;
1051 }
1052 }
1053 return null;
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001054 } finally {
1055 try {
1056 pfd.close();
1057 } catch (IOException ignore) {
1058 }
1059 }
1060 } else if (shortcut.hasIconResource()) {
Makoto Onuki2d895c32016-12-02 15:48:40 -08001061 return loadDrawableResourceFromPackage(shortcut.getPackage(),
1062 shortcut.getIconResourceId(), shortcut.getUserHandle(), density);
1063 } else if (shortcut.getIcon() != null) {
1064 // This happens if a shortcut is pending-approval.
1065 final Icon icon = shortcut.getIcon();
1066 switch (icon.getType()) {
1067 case Icon.TYPE_RESOURCE: {
1068 return loadDrawableResourceFromPackage(shortcut.getPackage(),
1069 icon.getResId(), shortcut.getUserHandle(), density);
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001070 }
Hyunyoung Songf281e7a2017-02-13 10:57:42 -08001071 case Icon.TYPE_BITMAP:
Hyunyoung Songe4179e22017-03-01 12:51:26 -08001072 case Icon.TYPE_ADAPTIVE_BITMAP: {
Makoto Onuki2d895c32016-12-02 15:48:40 -08001073 return icon.loadDrawable(mContext);
1074 }
1075 default:
1076 return null; // Shouldn't happen though.
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001077 }
1078 } else {
1079 return null; // Has no icon.
1080 }
Makoto Onuki20c95f82016-05-11 16:51:01 -07001081 }
1082
Makoto Onuki2d895c32016-12-02 15:48:40 -08001083 private Drawable loadDrawableResourceFromPackage(String packageName, int resId,
1084 UserHandle user, int density) {
1085 try {
1086 if (resId == 0) {
1087 return null; // Shouldn't happen but just in case.
1088 }
1089 final ApplicationInfo ai = getApplicationInfo(packageName, /* flags =*/ 0, user);
1090 final Resources res = mContext.getPackageManager().getResourcesForApplication(ai);
1091 return res.getDrawableForDensity(resId, density);
1092 } catch (NameNotFoundException | Resources.NotFoundException e) {
1093 return null;
1094 }
1095 }
1096
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001097 /**
1098 * Returns the shortcut icon with badging appropriate for the profile.
1099 *
Makoto Onukife9c9662016-07-25 15:12:23 -07001100 * <p>The calling launcher application must be allowed to access the shortcut information,
1101 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki4a910962016-07-07 13:57:34 -07001102 *
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001103 * @param density Optional density for the icon, or 0 to use the default density. Use
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001104 * @return A badged icon for the shortcut.
Makoto Onuki02f338e2016-07-29 09:40:40 -07001105 * @throws IllegalStateException when the user is locked, or when the {@code user} user
1106 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -07001107 *
1108 * @see ShortcutManager
Makoto Onukife9c9662016-07-25 15:12:23 -07001109 * @see #getShortcutIconDrawable(ShortcutInfo, int)
Makoto Onuki4a910962016-07-07 13:57:34 -07001110 * @see DisplayMetrics
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001111 */
1112 public Drawable getShortcutBadgedIconDrawable(ShortcutInfo shortcut, int density) {
1113 final Drawable originalIcon = getShortcutIconDrawable(shortcut, density);
1114
1115 return (originalIcon == null) ? null : mContext.getPackageManager().getUserBadgedIcon(
1116 originalIcon, shortcut.getUserHandle());
Makoto Onuki20c95f82016-05-11 16:51:01 -07001117 }
1118
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001119 /**
Makoto Onuki4a910962016-07-07 13:57:34 -07001120 * Starts a shortcut.
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001121 *
Makoto Onukife9c9662016-07-25 15:12:23 -07001122 * <p>The calling launcher application must be allowed to access the shortcut information,
1123 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001124 *
Makoto Onuki43204b82016-03-08 16:16:44 -08001125 * @param packageName The target shortcut package name.
1126 * @param shortcutId The target shortcut ID.
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001127 * @param sourceBounds The Rect containing the source bounds of the clicked icon.
1128 * @param startActivityOptions Options to pass to startActivity.
1129 * @param user The UserHandle of the profile.
Makoto Onuki02f338e2016-07-29 09:40:40 -07001130 * @throws IllegalStateException when the user is locked, or when the {@code user} user
1131 * is locked or not running.
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001132 *
1133 * @throws android.content.ActivityNotFoundException failed to start shortcut. (e.g.
1134 * the shortcut no longer exists, is disabled, the intent receiver activity doesn't exist, etc)
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001135 */
Makoto Onukid6880792016-06-29 13:37:43 -07001136 public void startShortcut(@NonNull String packageName, @NonNull String shortcutId,
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001137 @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
1138 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -08001139 logErrorForInvalidProfileAccess(user);
1140
Makoto Onukid6880792016-06-29 13:37:43 -07001141 startShortcut(packageName, shortcutId, sourceBounds, startActivityOptions,
Makoto Onukiabe84422016-04-07 09:41:19 -07001142 user.getIdentifier());
1143 }
1144
1145 /**
1146 * Launches a shortcut.
1147 *
Makoto Onukife9c9662016-07-25 15:12:23 -07001148 * <p>The calling launcher application must be allowed to access the shortcut information,
1149 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onukiabe84422016-04-07 09:41:19 -07001150 *
1151 * @param shortcut The target shortcut.
1152 * @param sourceBounds The Rect containing the source bounds of the clicked icon.
1153 * @param startActivityOptions Options to pass to startActivity.
Makoto Onuki02f338e2016-07-29 09:40:40 -07001154 * @throws IllegalStateException when the user is locked, or when the {@code user} user
1155 * is locked or not running.
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001156 *
1157 * @throws android.content.ActivityNotFoundException failed to start shortcut. (e.g.
1158 * the shortcut no longer exists, is disabled, the intent receiver activity doesn't exist, etc)
Makoto Onukiabe84422016-04-07 09:41:19 -07001159 */
Makoto Onukid6880792016-06-29 13:37:43 -07001160 public void startShortcut(@NonNull ShortcutInfo shortcut,
Makoto Onukiabe84422016-04-07 09:41:19 -07001161 @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions) {
Makoto Onukid6880792016-06-29 13:37:43 -07001162 startShortcut(shortcut.getPackage(), shortcut.getId(),
Makoto Onukiabe84422016-04-07 09:41:19 -07001163 sourceBounds, startActivityOptions,
1164 shortcut.getUserId());
1165 }
1166
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001167 @UnsupportedAppUsage
Makoto Onukid6880792016-06-29 13:37:43 -07001168 private void startShortcut(@NonNull String packageName, @NonNull String shortcutId,
Makoto Onukiabe84422016-04-07 09:41:19 -07001169 @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
1170 int userId) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001171 try {
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001172 final boolean success =
1173 mService.startShortcut(mContext.getPackageName(), packageName, shortcutId,
Makoto Onukiabe84422016-04-07 09:41:19 -07001174 sourceBounds, startActivityOptions, userId);
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001175 if (!success) {
1176 throw new ActivityNotFoundException("Shortcut could not be started");
1177 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001178 } catch (RemoteException e) {
1179 throw e.rethrowFromSystemServer();
1180 }
1181 }
Kenny Guy53fa4ec2014-04-29 14:24:18 +01001182
1183 /**
Jon Miranda2b340a22019-01-25 14:03:49 -08001184 * Registers a callback for changes to packages in this user and managed profiles.
Kenny Guyc01545372014-06-16 14:17:26 +01001185 *
Kenny Guy10a574f2014-08-26 16:17:58 +01001186 * @param callback The callback to register.
Kenny Guyc01545372014-06-16 14:17:26 +01001187 */
Kenny Guy10a574f2014-08-26 16:17:58 +01001188 public void registerCallback(Callback callback) {
1189 registerCallback(callback, null);
Kenny Guyb42c89b2014-07-28 19:20:07 +01001190 }
1191
1192 /**
Jon Miranda2b340a22019-01-25 14:03:49 -08001193 * Registers a callback for changes to packages in this user and managed profiles.
Kenny Guyb42c89b2014-07-28 19:20:07 +01001194 *
Kenny Guy10a574f2014-08-26 16:17:58 +01001195 * @param callback The callback to register.
Kenny Guyb42c89b2014-07-28 19:20:07 +01001196 * @param handler that should be used to post callbacks on, may be null.
1197 */
Kenny Guy10a574f2014-08-26 16:17:58 +01001198 public void registerCallback(Callback callback, Handler handler) {
Kenny Guyc01545372014-06-16 14:17:26 +01001199 synchronized (this) {
Kenny Guy172a2162015-06-19 17:21:28 +01001200 if (callback != null && findCallbackLocked(callback) < 0) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001201 boolean addedFirstCallback = mCallbacks.size() == 0;
1202 addCallbackLocked(callback, handler);
1203 if (addedFirstCallback) {
Kenny Guyc01545372014-06-16 14:17:26 +01001204 try {
Makoto Onuki4dbe0de2016-03-14 17:31:49 -07001205 mService.addOnAppsChangedListener(mContext.getPackageName(),
1206 mAppsChangedListener);
Kenny Guyc01545372014-06-16 14:17:26 +01001207 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001208 throw re.rethrowFromSystemServer();
Kenny Guyc01545372014-06-16 14:17:26 +01001209 }
1210 }
1211 }
1212 }
1213 }
1214
1215 /**
Kenny Guy10a574f2014-08-26 16:17:58 +01001216 * Unregisters a callback that was previously registered.
Kenny Guyc01545372014-06-16 14:17:26 +01001217 *
Kenny Guy10a574f2014-08-26 16:17:58 +01001218 * @param callback The callback to unregister.
1219 * @see #registerCallback(Callback)
Kenny Guyc01545372014-06-16 14:17:26 +01001220 */
Kenny Guy10a574f2014-08-26 16:17:58 +01001221 public void unregisterCallback(Callback callback) {
Kenny Guyc01545372014-06-16 14:17:26 +01001222 synchronized (this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001223 removeCallbackLocked(callback);
Kenny Guy44b6dee2014-07-10 18:10:14 +01001224 if (mCallbacks.size() == 0) {
Amith Yamasanie781c812014-05-28 15:28:18 -07001225 try {
1226 mService.removeOnAppsChangedListener(mAppsChangedListener);
1227 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001228 throw re.rethrowFromSystemServer();
Amith Yamasanie781c812014-05-28 15:28:18 -07001229 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001230 }
1231 }
1232 }
1233
Kenny Guy172a2162015-06-19 17:21:28 +01001234 /** @return position in mCallbacks for callback or -1 if not present. */
1235 private int findCallbackLocked(Callback callback) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001236 if (callback == null) {
1237 throw new IllegalArgumentException("Callback cannot be null");
1238 }
1239 final int size = mCallbacks.size();
1240 for (int i = 0; i < size; ++i) {
1241 if (mCallbacks.get(i).mCallback == callback) {
Kenny Guy172a2162015-06-19 17:21:28 +01001242 return i;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001243 }
1244 }
Kenny Guy172a2162015-06-19 17:21:28 +01001245 return -1;
1246 }
1247
1248 private void removeCallbackLocked(Callback callback) {
1249 int pos = findCallbackLocked(callback);
1250 if (pos >= 0) {
1251 mCallbacks.remove(pos);
1252 }
Kenny Guyb42c89b2014-07-28 19:20:07 +01001253 }
1254
Kenny Guyf939dba2014-08-15 15:32:34 +01001255 private void addCallbackLocked(Callback callback, Handler handler) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001256 // Remove if already present.
1257 removeCallbackLocked(callback);
1258 if (handler == null) {
1259 handler = new Handler();
1260 }
1261 CallbackMessageHandler toAdd = new CallbackMessageHandler(handler.getLooper(), callback);
1262 mCallbacks.add(toAdd);
1263 }
1264
Amith Yamasani4f582632014-02-19 14:31:52 -08001265 private IOnAppsChangedListener.Stub mAppsChangedListener = new IOnAppsChangedListener.Stub() {
1266
1267 @Override
Kenny Guyb42c89b2014-07-28 19:20:07 +01001268 public void onPackageRemoved(UserHandle user, String packageName)
1269 throws RemoteException {
Amith Yamasani4f582632014-02-19 14:31:52 -08001270 if (DEBUG) {
1271 Log.d(TAG, "onPackageRemoved " + user.getIdentifier() + "," + packageName);
1272 }
1273 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001274 for (CallbackMessageHandler callback : mCallbacks) {
1275 callback.postOnPackageRemoved(packageName, user);
Kenny Guyc01545372014-06-16 14:17:26 +01001276 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001277 }
1278 }
1279
1280 @Override
1281 public void onPackageChanged(UserHandle user, String packageName) throws RemoteException {
1282 if (DEBUG) {
1283 Log.d(TAG, "onPackageChanged " + user.getIdentifier() + "," + packageName);
1284 }
1285 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001286 for (CallbackMessageHandler callback : mCallbacks) {
1287 callback.postOnPackageChanged(packageName, user);
Kenny Guyc01545372014-06-16 14:17:26 +01001288 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001289 }
1290 }
1291
1292 @Override
1293 public void onPackageAdded(UserHandle user, String packageName) throws RemoteException {
1294 if (DEBUG) {
1295 Log.d(TAG, "onPackageAdded " + user.getIdentifier() + "," + packageName);
1296 }
1297 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001298 for (CallbackMessageHandler callback : mCallbacks) {
1299 callback.postOnPackageAdded(packageName, user);
Kenny Guyc01545372014-06-16 14:17:26 +01001300 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001301 }
1302 }
1303
1304 @Override
1305 public void onPackagesAvailable(UserHandle user, String[] packageNames, boolean replacing)
1306 throws RemoteException {
1307 if (DEBUG) {
1308 Log.d(TAG, "onPackagesAvailable " + user.getIdentifier() + "," + packageNames);
1309 }
1310 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001311 for (CallbackMessageHandler callback : mCallbacks) {
1312 callback.postOnPackagesAvailable(packageNames, user, replacing);
Kenny Guyc01545372014-06-16 14:17:26 +01001313 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001314 }
1315 }
1316
1317 @Override
1318 public void onPackagesUnavailable(UserHandle user, String[] packageNames, boolean replacing)
1319 throws RemoteException {
1320 if (DEBUG) {
1321 Log.d(TAG, "onPackagesUnavailable " + user.getIdentifier() + "," + packageNames);
1322 }
1323 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001324 for (CallbackMessageHandler callback : mCallbacks) {
1325 callback.postOnPackagesUnavailable(packageNames, user, replacing);
Kenny Guyc01545372014-06-16 14:17:26 +01001326 }
Kenny Guy77242752016-01-15 13:29:06 +00001327 }
1328 }
1329
1330 @Override
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001331 public void onPackagesSuspended(UserHandle user, String[] packageNames,
1332 Bundle launcherExtras)
Kenny Guy77242752016-01-15 13:29:06 +00001333 throws RemoteException {
1334 if (DEBUG) {
1335 Log.d(TAG, "onPackagesSuspended " + user.getIdentifier() + "," + packageNames);
1336 }
1337 synchronized (LauncherApps.this) {
1338 for (CallbackMessageHandler callback : mCallbacks) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001339 callback.postOnPackagesSuspended(packageNames, launcherExtras, user);
Kenny Guy77242752016-01-15 13:29:06 +00001340 }
1341 }
1342 }
1343
1344 @Override
1345 public void onPackagesUnsuspended(UserHandle user, String[] packageNames)
1346 throws RemoteException {
1347 if (DEBUG) {
1348 Log.d(TAG, "onPackagesUnsuspended " + user.getIdentifier() + "," + packageNames);
1349 }
1350 synchronized (LauncherApps.this) {
1351 for (CallbackMessageHandler callback : mCallbacks) {
1352 callback.postOnPackagesUnsuspended(packageNames, user);
1353 }
1354 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001355 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001356
1357 @Override
1358 public void onShortcutChanged(UserHandle user, String packageName,
1359 ParceledListSlice shortcuts) {
1360 if (DEBUG) {
1361 Log.d(TAG, "onShortcutChanged " + user.getIdentifier() + "," + packageName);
1362 }
1363 final List<ShortcutInfo> list = shortcuts.getList();
1364 synchronized (LauncherApps.this) {
1365 for (CallbackMessageHandler callback : mCallbacks) {
1366 callback.postOnShortcutChanged(packageName, user, list);
1367 }
1368 }
1369 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001370 };
Kenny Guyb42c89b2014-07-28 19:20:07 +01001371
1372 private static class CallbackMessageHandler extends Handler {
1373 private static final int MSG_ADDED = 1;
1374 private static final int MSG_REMOVED = 2;
1375 private static final int MSG_CHANGED = 3;
1376 private static final int MSG_AVAILABLE = 4;
1377 private static final int MSG_UNAVAILABLE = 5;
Kenny Guy77242752016-01-15 13:29:06 +00001378 private static final int MSG_SUSPENDED = 6;
1379 private static final int MSG_UNSUSPENDED = 7;
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001380 private static final int MSG_SHORTCUT_CHANGED = 8;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001381
Kenny Guyf939dba2014-08-15 15:32:34 +01001382 private LauncherApps.Callback mCallback;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001383
1384 private static class CallbackInfo {
1385 String[] packageNames;
1386 String packageName;
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001387 Bundle launcherExtras;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001388 boolean replacing;
1389 UserHandle user;
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001390 List<ShortcutInfo> shortcuts;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001391 }
1392
Kenny Guyf939dba2014-08-15 15:32:34 +01001393 public CallbackMessageHandler(Looper looper, LauncherApps.Callback callback) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001394 super(looper, null, true);
1395 mCallback = callback;
1396 }
1397
1398 @Override
1399 public void handleMessage(Message msg) {
1400 if (mCallback == null || !(msg.obj instanceof CallbackInfo)) {
1401 return;
1402 }
1403 CallbackInfo info = (CallbackInfo) msg.obj;
1404 switch (msg.what) {
1405 case MSG_ADDED:
1406 mCallback.onPackageAdded(info.packageName, info.user);
1407 break;
1408 case MSG_REMOVED:
1409 mCallback.onPackageRemoved(info.packageName, info.user);
1410 break;
1411 case MSG_CHANGED:
1412 mCallback.onPackageChanged(info.packageName, info.user);
1413 break;
1414 case MSG_AVAILABLE:
1415 mCallback.onPackagesAvailable(info.packageNames, info.user, info.replacing);
1416 break;
1417 case MSG_UNAVAILABLE:
1418 mCallback.onPackagesUnavailable(info.packageNames, info.user, info.replacing);
1419 break;
Kenny Guy77242752016-01-15 13:29:06 +00001420 case MSG_SUSPENDED:
Suprabh Shukla96212bc2018-04-10 15:04:51 -07001421 mCallback.onPackagesSuspended(info.packageNames, info.user, info.launcherExtras
1422 );
Kenny Guy77242752016-01-15 13:29:06 +00001423 break;
1424 case MSG_UNSUSPENDED:
1425 mCallback.onPackagesUnsuspended(info.packageNames, info.user);
1426 break;
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001427 case MSG_SHORTCUT_CHANGED:
1428 mCallback.onShortcutsChanged(info.packageName, info.shortcuts, info.user);
1429 break;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001430 }
1431 }
1432
1433 public void postOnPackageAdded(String packageName, UserHandle user) {
1434 CallbackInfo info = new CallbackInfo();
1435 info.packageName = packageName;
1436 info.user = user;
1437 obtainMessage(MSG_ADDED, info).sendToTarget();
1438 }
1439
1440 public void postOnPackageRemoved(String packageName, UserHandle user) {
1441 CallbackInfo info = new CallbackInfo();
1442 info.packageName = packageName;
1443 info.user = user;
1444 obtainMessage(MSG_REMOVED, info).sendToTarget();
1445 }
1446
1447 public void postOnPackageChanged(String packageName, UserHandle user) {
1448 CallbackInfo info = new CallbackInfo();
1449 info.packageName = packageName;
1450 info.user = user;
1451 obtainMessage(MSG_CHANGED, info).sendToTarget();
1452 }
1453
1454 public void postOnPackagesAvailable(String[] packageNames, UserHandle user,
1455 boolean replacing) {
1456 CallbackInfo info = new CallbackInfo();
1457 info.packageNames = packageNames;
1458 info.replacing = replacing;
1459 info.user = user;
1460 obtainMessage(MSG_AVAILABLE, info).sendToTarget();
1461 }
1462
1463 public void postOnPackagesUnavailable(String[] packageNames, UserHandle user,
1464 boolean replacing) {
1465 CallbackInfo info = new CallbackInfo();
1466 info.packageNames = packageNames;
1467 info.replacing = replacing;
1468 info.user = user;
1469 obtainMessage(MSG_UNAVAILABLE, info).sendToTarget();
1470 }
Kenny Guy77242752016-01-15 13:29:06 +00001471
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001472 public void postOnPackagesSuspended(String[] packageNames, Bundle launcherExtras,
1473 UserHandle user) {
Kenny Guy77242752016-01-15 13:29:06 +00001474 CallbackInfo info = new CallbackInfo();
1475 info.packageNames = packageNames;
1476 info.user = user;
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001477 info.launcherExtras = launcherExtras;
Kenny Guy77242752016-01-15 13:29:06 +00001478 obtainMessage(MSG_SUSPENDED, info).sendToTarget();
1479 }
1480
1481 public void postOnPackagesUnsuspended(String[] packageNames, UserHandle user) {
1482 CallbackInfo info = new CallbackInfo();
1483 info.packageNames = packageNames;
1484 info.user = user;
1485 obtainMessage(MSG_UNSUSPENDED, info).sendToTarget();
1486 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001487
1488 public void postOnShortcutChanged(String packageName, UserHandle user,
1489 List<ShortcutInfo> shortcuts) {
1490 CallbackInfo info = new CallbackInfo();
1491 info.packageName = packageName;
1492 info.user = user;
1493 info.shortcuts = shortcuts;
1494 obtainMessage(MSG_SHORTCUT_CHANGED, info).sendToTarget();
1495 }
Kenny Guyb42c89b2014-07-28 19:20:07 +01001496 }
Makoto Onuki2d895c32016-12-02 15:48:40 -08001497
1498 /**
Jon Miranda2b340a22019-01-25 14:03:49 -08001499 * Register a callback to watch for session lifecycle events in this user and managed profiles.
1500 * @param callback The callback to register.
1501 * @param executor {@link Executor} to handle the callbacks, cannot be null.
1502 *
1503 * @see PackageInstaller#registerSessionCallback(SessionCallback)
1504 */
1505 public void registerPackageInstallerSessionCallback(
1506 @NonNull @CallbackExecutor Executor executor, @NonNull SessionCallback callback) {
1507 if (executor == null) {
1508 throw new NullPointerException("Executor must not be null");
1509 }
1510
1511 synchronized (mDelegates) {
1512 final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
1513 executor);
1514 try {
1515 mService.registerPackageInstallerCallback(mContext.getPackageName(),
1516 delegate);
1517 } catch (RemoteException e) {
1518 throw e.rethrowFromSystemServer();
1519 }
1520 mDelegates.add(delegate);
1521 }
1522 }
1523
1524 /**
1525 * Unregisters a callback that was previously registered.
1526 *
1527 * @param callback The callback to unregister.
1528 * @see #registerPackageInstallerSessionCallback(Executor, SessionCallback)
1529 */
Jon Miranda93505982019-03-08 09:33:42 -08001530 public void unregisterPackageInstallerSessionCallback(@NonNull SessionCallback callback) {
Jon Miranda2b340a22019-01-25 14:03:49 -08001531 synchronized (mDelegates) {
1532 for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
1533 final SessionCallbackDelegate delegate = i.next();
1534 if (delegate.mCallback == callback) {
1535 mPm.getPackageInstaller().unregisterSessionCallback(delegate.mCallback);
1536 i.remove();
1537 }
1538 }
1539 }
1540 }
1541
1542 /**
1543 * Return list of all known install sessions in this user and managed profiles, regardless
1544 * of the installer.
1545 *
1546 * @see PackageInstaller#getAllSessions()
1547 */
1548 public @NonNull List<SessionInfo> getAllPackageInstallerSessions() {
1549 try {
1550 return mService.getAllSessions(mContext.getPackageName()).getList();
1551 } catch (RemoteException e) {
1552 throw e.rethrowFromSystemServer();
1553 }
1554 }
1555
1556 /**
Makoto Onuki2d895c32016-12-02 15:48:40 -08001557 * A helper method to extract a {@link PinItemRequest} set to
1558 * the {@link #EXTRA_PIN_ITEM_REQUEST} extra.
1559 */
1560 public PinItemRequest getPinItemRequest(Intent intent) {
1561 return intent.getParcelableExtra(EXTRA_PIN_ITEM_REQUEST);
1562 }
1563
1564 /**
Sunny Goyal7f7372a2017-01-24 11:53:54 -08001565 * Represents a "pin shortcut" or a "pin appwidget" request made by an app, which is sent with
1566 * an {@link #ACTION_CONFIRM_PIN_SHORTCUT} or {@link #ACTION_CONFIRM_PIN_APPWIDGET} intent
1567 * respectively to the default launcher app.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001568 *
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001569 * <h3>Request of the {@link #REQUEST_TYPE_SHORTCUT} type.
Makoto Onuki0c280712017-01-19 15:14:27 -08001570 *
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001571 * <p>A {@link #REQUEST_TYPE_SHORTCUT} request represents a request to pin a
1572 * {@link ShortcutInfo}. If the launcher accepts a request, call {@link #accept()},
1573 * or {@link #accept(Bundle)} with a null or empty Bundle. No options are defined for
1574 * pin-shortcuts requests.
1575 *
1576 * <p>{@link #getShortcutInfo()} always returns a non-null {@link ShortcutInfo} for this type.
1577 *
1578 * <p>The launcher may receive a request with a {@link ShortcutInfo} that is already pinned, in
1579 * which case {@link ShortcutInfo#isPinned()} returns true. This means the user wants to create
1580 * another pinned shortcut for a shortcut that's already pinned. If the launcher accepts it,
1581 * {@link #accept()} must still be called even though the shortcut is already pinned, and
1582 * create a new pinned shortcut icon for it.
1583 *
1584 * <p>See also {@link ShortcutManager} for more details.
1585 *
1586 * <h3>Request of the {@link #REQUEST_TYPE_APPWIDGET} type.
1587 *
1588 * <p>A {@link #REQUEST_TYPE_SHORTCUT} request represents a request to pin a
1589 * an AppWidget. If the launcher accepts a request, call {@link #accept(Bundle)} with
1590 * the appwidget integer ID set to the
1591 * {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID} extra.
1592 *
1593 * <p>{@link #getAppWidgetProviderInfo(Context)} always returns a non-null
1594 * {@link AppWidgetProviderInfo} for this type.
1595 *
1596 * <p>See also {@link AppWidgetManager} for more details.
Sunny Goyal7f7372a2017-01-24 11:53:54 -08001597 *
Makoto Onuki2d895c32016-12-02 15:48:40 -08001598 * @see #EXTRA_PIN_ITEM_REQUEST
1599 * @see #getPinItemRequest(Intent)
1600 */
1601 public static final class PinItemRequest implements Parcelable {
1602
1603 /** This is a request to pin shortcut. */
1604 public static final int REQUEST_TYPE_SHORTCUT = 1;
1605
Sunny Goyal87a563e2017-01-01 19:42:45 -08001606 /** This is a request to pin app widget. */
1607 public static final int REQUEST_TYPE_APPWIDGET = 2;
1608
Makoto Onukif5663b12017-01-09 14:09:56 -08001609 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -07001610 @IntDef(prefix = { "REQUEST_TYPE_" }, value = {
1611 REQUEST_TYPE_SHORTCUT,
1612 REQUEST_TYPE_APPWIDGET
1613 })
Makoto Onuki2d895c32016-12-02 15:48:40 -08001614 @Retention(RetentionPolicy.SOURCE)
1615 public @interface RequestType {}
1616
1617 private final int mRequestType;
Makoto Onuki2d895c32016-12-02 15:48:40 -08001618 private final IPinItemRequest mInner;
1619
1620 /**
1621 * @hide
1622 */
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001623 public PinItemRequest(IPinItemRequest inner, int type) {
Sunny Goyal87a563e2017-01-01 19:42:45 -08001624 mInner = inner;
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001625 mRequestType = type;
Makoto Onuki2d895c32016-12-02 15:48:40 -08001626 }
1627
1628 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001629 * Represents the type of a request, which is one of the {@code REQUEST_TYPE_} constants.
1630 *
1631 * @return one of the {@code REQUEST_TYPE_} constants.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001632 */
1633 @RequestType
1634 public int getRequestType() {
1635 return mRequestType;
1636 }
1637
1638 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001639 * {@link ShortcutInfo} sent by the requesting app.
1640 * Always non-null for a {@link #REQUEST_TYPE_SHORTCUT} request, and always null for a
1641 * different request type.
1642 *
1643 * @return requested {@link ShortcutInfo} when a request is of the
1644 * {@link #REQUEST_TYPE_SHORTCUT} type. Null otherwise.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001645 */
1646 @Nullable
1647 public ShortcutInfo getShortcutInfo() {
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001648 try {
1649 return mInner.getShortcutInfo();
1650 } catch (RemoteException e) {
1651 throw e.rethrowAsRuntimeException();
1652 }
Makoto Onuki2d895c32016-12-02 15:48:40 -08001653 }
1654
1655 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001656 * {@link AppWidgetProviderInfo} sent by the requesting app.
1657 * Always non-null for a {@link #REQUEST_TYPE_APPWIDGET} request, and always null for a
1658 * different request type.
1659 *
Sunny Goyale7712ad2018-03-08 11:23:06 -08001660 * <p>Launcher should not show any configuration activity associated with the provider, and
1661 * assume that the widget is already fully configured. Upon accepting the widget, it should
1662 * pass the widgetId in {@link #accept(Bundle)}.
1663 *
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001664 * @return requested {@link AppWidgetProviderInfo} when a request is of the
1665 * {@link #REQUEST_TYPE_APPWIDGET} type. Null otherwise.
Sunny Goyal87a563e2017-01-01 19:42:45 -08001666 */
1667 @Nullable
Sunny Goyal970d4b42017-01-19 15:07:36 -08001668 public AppWidgetProviderInfo getAppWidgetProviderInfo(Context context) {
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001669 try {
1670 final AppWidgetProviderInfo info = mInner.getAppWidgetProviderInfo();
1671 if (info == null) {
1672 return null;
1673 }
Sunny Goyal970d4b42017-01-19 15:07:36 -08001674 info.updateDimensions(context.getResources().getDisplayMetrics());
1675 return info;
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001676 } catch (RemoteException e) {
1677 throw e.rethrowAsRuntimeException();
Sunny Goyal970d4b42017-01-19 15:07:36 -08001678 }
Sunny Goyal87a563e2017-01-01 19:42:45 -08001679 }
1680
1681 /**
Sunny Goyal4ad6b572017-02-28 11:11:51 -08001682 * Any extras sent by the requesting app.
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001683 *
1684 * @return For a shortcut request, this method always return null. For an AppWidget
1685 * request, this method returns the extras passed to the
1686 * {@link android.appwidget.AppWidgetManager#requestPinAppWidget(
1687 * ComponentName, Bundle, PendingIntent)} API. See {@link AppWidgetManager} for details.
Sunny Goyal4ad6b572017-02-28 11:11:51 -08001688 */
1689 @Nullable
1690 public Bundle getExtras() {
1691 try {
1692 return mInner.getExtras();
1693 } catch (RemoteException e) {
1694 throw e.rethrowAsRuntimeException();
1695 }
1696 }
1697
1698 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001699 * Return whether a request is still valid.
1700 *
1701 * @return {@code TRUE} if a request is valid and {@link #accept(Bundle)} may be called.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001702 */
1703 public boolean isValid() {
1704 try {
1705 return mInner.isValid();
1706 } catch (RemoteException e) {
1707 return false;
1708 }
1709 }
1710
1711 /**
1712 * Called by the receiving launcher app when the user accepts the request.
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001713 *
1714 * @param options must be set for a {@link #REQUEST_TYPE_APPWIDGET} request.
1715 *
1716 * @return {@code TRUE} if the shortcut or the AppWidget has actually been pinned.
1717 * {@code FALSE} if the item hasn't been pinned, for example, because the request had
1718 * already been canceled, in which case the launcher must not pin the requested item.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001719 */
1720 public boolean accept(@Nullable Bundle options) {
1721 try {
1722 return mInner.accept(options);
1723 } catch (RemoteException e) {
1724 throw e.rethrowFromSystemServer();
1725 }
1726 }
1727
1728 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001729 * Called by the receiving launcher app when the user accepts the request, with no options.
1730 *
1731 * @return {@code TRUE} if the shortcut or the AppWidget has actually been pinned.
1732 * {@code FALSE} if the item hasn't been pinned, for example, because the request had
1733 * already been canceled, in which case the launcher must not pin the requested item.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001734 */
1735 public boolean accept() {
1736 return accept(/* options= */ null);
1737 }
1738
1739 private PinItemRequest(Parcel source) {
1740 final ClassLoader cl = getClass().getClassLoader();
1741
1742 mRequestType = source.readInt();
Makoto Onuki2d895c32016-12-02 15:48:40 -08001743 mInner = IPinItemRequest.Stub.asInterface(source.readStrongBinder());
1744 }
1745
1746 @Override
1747 public void writeToParcel(Parcel dest, int flags) {
1748 dest.writeInt(mRequestType);
Makoto Onuki2d895c32016-12-02 15:48:40 -08001749 dest.writeStrongBinder(mInner.asBinder());
1750 }
1751
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001752 public static final @android.annotation.NonNull Creator<PinItemRequest> CREATOR =
Makoto Onuki2d895c32016-12-02 15:48:40 -08001753 new Creator<PinItemRequest>() {
1754 public PinItemRequest createFromParcel(Parcel source) {
1755 return new PinItemRequest(source);
1756 }
1757 public PinItemRequest[] newArray(int size) {
1758 return new PinItemRequest[size];
1759 }
1760 };
1761
1762 @Override
1763 public int describeContents() {
1764 return 0;
1765 }
1766 }
Varun Shah2546cef2019-01-11 15:50:54 -08001767
1768 /**
1769 * A class that encapsulates information about the usage limit set for an app or
1770 * a group of apps.
1771 *
Varun Shah9c6f72b2019-01-25 21:13:56 -08001772 * <p>The launcher can query specifics about the usage limit such as how much usage time
1773 * the limit has and how much of the total usage time is remaining via the APIs available
1774 * in this class.
Varun Shah2546cef2019-01-11 15:50:54 -08001775 *
1776 * @see #getAppUsageLimit(String, UserHandle)
Sunny Goyalbeee1972019-03-29 11:38:16 -07001777 * @hide
Varun Shah2546cef2019-01-11 15:50:54 -08001778 */
Sunny Goyalbeee1972019-03-29 11:38:16 -07001779 @SystemApi
Varun Shah2546cef2019-01-11 15:50:54 -08001780 public static final class AppUsageLimit implements Parcelable {
Varun Shah2546cef2019-01-11 15:50:54 -08001781 private final long mTotalUsageLimit;
1782 private final long mUsageRemaining;
1783
1784 /** @hide */
Varun Shah9c6f72b2019-01-25 21:13:56 -08001785 public AppUsageLimit(long totalUsageLimit, long usageRemaining) {
Varun Shah2546cef2019-01-11 15:50:54 -08001786 this.mTotalUsageLimit = totalUsageLimit;
1787 this.mUsageRemaining = usageRemaining;
1788 }
1789
1790 /**
Varun Shah2546cef2019-01-11 15:50:54 -08001791 * Returns the total usage limit in milliseconds set for an app or a group of apps.
1792 *
1793 * @return the total usage limit in milliseconds
1794 */
1795 public long getTotalUsageLimit() {
1796 return mTotalUsageLimit;
1797 }
1798
1799 /**
1800 * Returns the usage remaining in milliseconds for an app or the group of apps
1801 * this limit refers to.
1802 *
1803 * @return the usage remaining in milliseconds
1804 */
1805 public long getUsageRemaining() {
1806 return mUsageRemaining;
1807 }
1808
1809 private AppUsageLimit(Parcel source) {
Varun Shah2546cef2019-01-11 15:50:54 -08001810 mTotalUsageLimit = source.readLong();
1811 mUsageRemaining = source.readLong();
1812 }
1813
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001814 public static final @android.annotation.NonNull Creator<AppUsageLimit> CREATOR = new Creator<AppUsageLimit>() {
Varun Shah2546cef2019-01-11 15:50:54 -08001815 @Override
1816 public AppUsageLimit createFromParcel(Parcel source) {
1817 return new AppUsageLimit(source);
1818 }
1819
1820 @Override
1821 public AppUsageLimit[] newArray(int size) {
1822 return new AppUsageLimit[size];
1823 }
1824 };
1825
1826 @Override
1827 public int describeContents() {
1828 return 0;
1829 }
1830
1831 @Override
1832 public void writeToParcel(Parcel dest, int flags) {
Varun Shah2546cef2019-01-11 15:50:54 -08001833 dest.writeLong(mTotalUsageLimit);
1834 dest.writeLong(mUsageRemaining);
1835 }
1836 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001837}