blob: 037a149bfe37165dece0dc7effc9ae072523ace9 [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;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010028import android.annotation.UnsupportedAppUsage;
Makoto Onukia37ac3d2017-04-14 12:33:10 -070029import android.app.PendingIntent;
30import android.appwidget.AppWidgetManager;
Sunny Goyal87a563e2017-01-01 19:42:45 -080031import android.appwidget.AppWidgetProviderInfo;
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 Onuki7c7fbf62017-04-14 11:03:56 -070065import com.android.internal.util.Preconditions;
66
Makoto Onuki04b9aab2016-05-23 17:13:30 -070067import java.io.IOException;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080068import java.lang.annotation.Retention;
69import java.lang.annotation.RetentionPolicy;
Amith Yamasani4f582632014-02-19 14:31:52 -080070import java.util.ArrayList;
Makoto Onukib6d35232016-04-04 15:57:17 -070071import java.util.Arrays;
Amith Yamasani4f582632014-02-19 14:31:52 -080072import java.util.Collections;
Jon Miranda2b340a22019-01-25 14:03:49 -080073import java.util.Iterator;
Amith Yamasani4f582632014-02-19 14:31:52 -080074import java.util.List;
Jon Miranda2b340a22019-01-25 14:03:49 -080075import java.util.concurrent.Executor;
Amith Yamasani4f582632014-02-19 14:31:52 -080076
77/**
78 * Class for retrieving a list of launchable activities for the current user and any associated
Makoto Onukiaecbd032017-01-19 12:11:11 -080079 * managed profiles that are visible to the current user, which can be retrieved with
80 * {@link #getProfiles}. This is mainly for use by launchers.
81 *
82 * Apps can be queried for each user profile.
Amith Yamasani4f582632014-02-19 14:31:52 -080083 * Since the PackageManager will not deliver package broadcasts for other profiles, you can register
84 * for package changes here.
Amith Yamasanie781c812014-05-28 15:28:18 -070085 * <p>
86 * To watch for managed profiles being added or removed, register for the following broadcasts:
87 * {@link Intent#ACTION_MANAGED_PROFILE_ADDED} and {@link Intent#ACTION_MANAGED_PROFILE_REMOVED}.
88 * <p>
Makoto Onukiaecbd032017-01-19 12:11:11 -080089 * Note as of Android O, apps on a managed profile are no longer allowed to access apps on the
90 * main profile. Apps can only access profiles returned by {@link #getProfiles()}.
Amith Yamasani4f582632014-02-19 14:31:52 -080091 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060092@SystemService(Context.LAUNCHER_APPS_SERVICE)
Amith Yamasani4f582632014-02-19 14:31:52 -080093public class LauncherApps {
94
95 static final String TAG = "LauncherApps";
96 static final boolean DEBUG = false;
97
Makoto Onuki2d895c32016-12-02 15:48:40 -080098 /**
99 * Activity Action: For the default launcher to show the confirmation dialog to create
100 * a pinned shortcut.
101 *
102 * <p>See the {@link ShortcutManager} javadoc for details.
103 *
104 * <p>
105 * Use {@link #getPinItemRequest(Intent)} to get a {@link PinItemRequest} object,
106 * and call {@link PinItemRequest#accept(Bundle)}
107 * if the user accepts. If the user doesn't accept, no further action is required.
108 *
109 * @see #EXTRA_PIN_ITEM_REQUEST
110 */
111 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
Sunny Goyal7f7372a2017-01-24 11:53:54 -0800112 public static final String ACTION_CONFIRM_PIN_SHORTCUT =
113 "android.content.pm.action.CONFIRM_PIN_SHORTCUT";
Makoto Onuki2d895c32016-12-02 15:48:40 -0800114
115 /**
Sunny Goyal7f7372a2017-01-24 11:53:54 -0800116 * Activity Action: For the default launcher to show the confirmation dialog to create
117 * a pinned app widget.
118 *
119 * <p>See the {@link android.appwidget.AppWidgetManager#requestPinAppWidget} javadoc for
120 * details.
121 *
122 * <p>
123 * Use {@link #getPinItemRequest(Intent)} to get a {@link PinItemRequest} object,
124 * and call {@link PinItemRequest#accept(Bundle)}
125 * if the user accepts. If the user doesn't accept, no further action is required.
126 *
127 * @see #EXTRA_PIN_ITEM_REQUEST
128 */
129 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
130 public static final String ACTION_CONFIRM_PIN_APPWIDGET =
131 "android.content.pm.action.CONFIRM_PIN_APPWIDGET";
132
133 /**
134 * An extra for {@link #ACTION_CONFIRM_PIN_SHORTCUT} &amp; {@link #ACTION_CONFIRM_PIN_APPWIDGET}
135 * containing a {@link PinItemRequest} of appropriate type asked to pin.
Makoto Onuki2d895c32016-12-02 15:48:40 -0800136 *
137 * <p>A helper function {@link #getPinItemRequest(Intent)} can be used
138 * instead of using this constant directly.
139 *
Sunny Goyal7f7372a2017-01-24 11:53:54 -0800140 * @see #ACTION_CONFIRM_PIN_SHORTCUT
141 * @see #ACTION_CONFIRM_PIN_APPWIDGET
Makoto Onuki2d895c32016-12-02 15:48:40 -0800142 */
143 public static final String EXTRA_PIN_ITEM_REQUEST =
144 "android.content.pm.extra.PIN_ITEM_REQUEST";
145
Makoto Onukide3c16c2017-01-26 11:39:31 -0800146 private final Context mContext;
Mathew Inwood8c854f82018-09-14 12:35:36 +0100147 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Makoto Onukide3c16c2017-01-26 11:39:31 -0800148 private final ILauncherApps mService;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100149 @UnsupportedAppUsage
Makoto Onukide3c16c2017-01-26 11:39:31 -0800150 private final PackageManager mPm;
151 private final UserManager mUserManager;
Amith Yamasani4f582632014-02-19 14:31:52 -0800152
Jon Miranda2b340a22019-01-25 14:03:49 -0800153 private final List<CallbackMessageHandler> mCallbacks = new ArrayList<>();
154 private final List<SessionCallbackDelegate> mDelegates = new ArrayList<>();
Kenny Guyc01545372014-06-16 14:17:26 +0100155
156 /**
157 * Callbacks for package changes to this and related managed profiles.
158 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100159 public static abstract class Callback {
Kenny Guyc01545372014-06-16 14:17:26 +0100160 /**
161 * Indicates that a package was removed from the specified profile.
162 *
Kenny Guyb42c89b2014-07-28 19:20:07 +0100163 * If a package is removed while being updated onPackageChanged will be
164 * called instead.
165 *
Kenny Guyc01545372014-06-16 14:17:26 +0100166 * @param packageName The name of the package that was removed.
167 * @param user The UserHandle of the profile that generated the change.
168 */
169 abstract public void onPackageRemoved(String packageName, UserHandle user);
170
171 /**
172 * Indicates that a package was added to the specified profile.
173 *
Kenny Guyb42c89b2014-07-28 19:20:07 +0100174 * If a package is added while being updated then onPackageChanged will be
175 * called instead.
176 *
Kenny Guyc01545372014-06-16 14:17:26 +0100177 * @param packageName The name of the package that was added.
178 * @param user The UserHandle of the profile that generated the change.
179 */
180 abstract public void onPackageAdded(String packageName, UserHandle user);
181
182 /**
183 * Indicates that a package was modified in the specified profile.
Kenny Guyb42c89b2014-07-28 19:20:07 +0100184 * This can happen, for example, when the package is updated or when
185 * one or more components are enabled or disabled.
Kenny Guyc01545372014-06-16 14:17:26 +0100186 *
187 * @param packageName The name of the package that has changed.
188 * @param user The UserHandle of the profile that generated the change.
189 */
190 abstract public void onPackageChanged(String packageName, UserHandle user);
191
192 /**
193 * Indicates that one or more packages have become available. For
194 * example, this can happen when a removable storage card has
195 * reappeared.
196 *
197 * @param packageNames The names of the packages that have become
198 * available.
199 * @param user The UserHandle of the profile that generated the change.
200 * @param replacing Indicates whether these packages are replacing
201 * existing ones.
202 */
203 abstract public void onPackagesAvailable(String[] packageNames, UserHandle user,
204 boolean replacing);
205
206 /**
207 * Indicates that one or more packages have become unavailable. For
208 * example, this can happen when a removable storage card has been
209 * removed.
210 *
211 * @param packageNames The names of the packages that have become
212 * unavailable.
213 * @param user The UserHandle of the profile that generated the change.
214 * @param replacing Indicates whether the packages are about to be
215 * replaced with new versions.
216 */
217 abstract public void onPackagesUnavailable(String[] packageNames, UserHandle user,
218 boolean replacing);
Kenny Guy77242752016-01-15 13:29:06 +0000219
220 /**
221 * Indicates that one or more packages have been suspended. For
222 * example, this can happen when a Device Administrator suspends
223 * an applicaton.
224 *
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700225 * <p>Note: On devices running {@link android.os.Build.VERSION_CODES#P Android P} or higher,
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700226 * any apps that override {@link #onPackagesSuspended(String[], UserHandle, Bundle)} will
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700227 * not receive this callback.
228 *
Kenny Guy77242752016-01-15 13:29:06 +0000229 * @param packageNames The names of the packages that have just been
230 * suspended.
231 * @param user The UserHandle of the profile that generated the change.
232 */
233 public void onPackagesSuspended(String[] packageNames, UserHandle user) {
234 }
235
236 /**
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700237 * Indicates that one or more packages have been suspended. A device administrator or an app
238 * with {@code android.permission.SUSPEND_APPS} can do this.
239 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700240 * <p>A suspending app with the permission {@code android.permission.SUSPEND_APPS} can
241 * optionally provide a {@link Bundle} of extra information that it deems helpful for the
242 * launcher to handle the suspended state of these packages. The contents of this
Suprabh Shukla3e03ab92018-04-11 16:03:49 -0700243 * {@link Bundle} are supposed to be a contract between the suspending app and the launcher.
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700244 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700245 * @param packageNames The names of the packages that have just been suspended.
246 * @param user the user for which the given packages were suspended.
247 * @param launcherExtras A {@link Bundle} of extras for the launcher, if provided to the
248 * system, {@code null} otherwise.
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700249 * @see PackageManager#isPackageSuspended()
250 * @see #getSuspendedPackageLauncherExtras(String, UserHandle)
251 */
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700252 public void onPackagesSuspended(String[] packageNames, UserHandle user,
253 @Nullable Bundle launcherExtras) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700254 onPackagesSuspended(packageNames, user);
255 }
256
257 /**
Kenny Guy77242752016-01-15 13:29:06 +0000258 * Indicates that one or more packages have been unsuspended. For
259 * example, this can happen when a Device Administrator unsuspends
260 * an applicaton.
261 *
262 * @param packageNames The names of the packages that have just been
263 * unsuspended.
264 * @param user The UserHandle of the profile that generated the change.
265 */
266 public void onPackagesUnsuspended(String[] packageNames, UserHandle user) {
267 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800268
269 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700270 * Indicates that one or more shortcuts of any kind (dynamic, pinned, or manifest)
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800271 * have been added, updated or removed.
272 *
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800273 * <p>Only the applications that are allowed to access the shortcut information,
274 * as defined in {@link #hasShortcutHostPermission()}, will receive it.
275 *
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800276 * @param packageName The name of the package that has the shortcuts.
Makoto Onukife9c9662016-07-25 15:12:23 -0700277 * @param shortcuts All shortcuts from the package (dynamic, manifest and/or pinned).
278 * Only "key" information will be provided, as defined in
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700279 * {@link ShortcutInfo#hasKeyFieldsOnly()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800280 * @param user The UserHandle of the profile that generated the change.
Makoto Onuki4a910962016-07-07 13:57:34 -0700281 *
282 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800283 */
284 public void onShortcutsChanged(@NonNull String packageName,
285 @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
286 }
287 }
288
289 /**
290 * Represents a query passed to {@link #getShortcuts(ShortcutQuery, UserHandle)}.
291 */
292 public static class ShortcutQuery {
293 /**
294 * Include dynamic shortcuts in the result.
295 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700296 public static final int FLAG_MATCH_DYNAMIC = 1 << 0;
297
298 /** @hide kept for unit tests */
299 @Deprecated
300 public static final int FLAG_GET_DYNAMIC = FLAG_MATCH_DYNAMIC;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800301
302 /**
303 * Include pinned shortcuts in the result.
Makoto Onuki88b4dcc2017-12-07 15:53:56 -0800304 *
305 * <p>If you are the selected assistant app, and wishes to fetch all shortcuts that the
306 * user owns on the launcher (or by other launchers, in case the user has multiple), use
307 * {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} instead.
308 *
309 * <p>If you're a regular launcher app, there's no way to get shortcuts pinned by other
310 * launchers, and {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} will be ignored. So use this
311 * flag to get own pinned shortcuts.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800312 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700313 public static final int FLAG_MATCH_PINNED = 1 << 1;
314
315 /** @hide kept for unit tests */
316 @Deprecated
317 public static final int FLAG_GET_PINNED = FLAG_MATCH_PINNED;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800318
319 /**
Makoto Onuki22fcc682016-05-17 14:52:19 -0700320 * Include manifest shortcuts in the result.
321 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700322 public static final int FLAG_MATCH_MANIFEST = 1 << 3;
323
324 /** @hide kept for unit tests */
325 @Deprecated
326 public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700327
Hakan Seyalioglu58fc95d2016-12-13 15:23:22 -0800328 /**
Makoto Onuki35559d62017-11-06 16:26:32 -0800329 * Include all pinned shortcuts by any launchers, not just by the caller,
Makoto Onuki634cecb2017-10-13 17:10:48 -0700330 * in the result.
Makoto Onuki35559d62017-11-06 16:26:32 -0800331 *
Makoto Onuki88b4dcc2017-12-07 15:53:56 -0800332 * <p>The caller must be the selected assistant app to use this flag, or have the system
Makoto Onuki35559d62017-11-06 16:26:32 -0800333 * {@code ACCESS_SHORTCUTS} permission.
Makoto Onuki88b4dcc2017-12-07 15:53:56 -0800334 *
335 * <p>If you are the selected assistant app, and wishes to fetch all shortcuts that the
336 * user owns on the launcher (or by other launchers, in case the user has multiple), use
337 * {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} instead.
338 *
339 * <p>If you're a regular launcher app (or any app that's not the selected assistant app)
340 * then this flag will be ignored.
Makoto Onuki634cecb2017-10-13 17:10:48 -0700341 */
Makoto Onuki35559d62017-11-06 16:26:32 -0800342 public static final int FLAG_MATCH_PINNED_BY_ANY_LAUNCHER = 1 << 10;
Makoto Onuki634cecb2017-10-13 17:10:48 -0700343
344 /**
345 * FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST
Hakan Seyalioglu58fc95d2016-12-13 15:23:22 -0800346 * @hide
347 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700348 public static final int FLAG_MATCH_ALL_KINDS =
Makoto Onuki634cecb2017-10-13 17:10:48 -0700349 FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST;
350
351 /**
352 * FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST | FLAG_MATCH_ALL_PINNED
353 * @hide
354 */
355 public static final int FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED =
Makoto Onuki35559d62017-11-06 16:26:32 -0800356 FLAG_MATCH_ALL_KINDS | FLAG_MATCH_PINNED_BY_ANY_LAUNCHER;
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700357
Makoto Onukib5a012f2016-06-21 11:13:53 -0700358 /** @hide kept for unit tests */
359 @Deprecated
360 public static final int FLAG_GET_ALL_KINDS = FLAG_MATCH_ALL_KINDS;
361
Makoto Onuki22fcc682016-05-17 14:52:19 -0700362 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700363 * Requests "key" fields only. See {@link ShortcutInfo#hasKeyFieldsOnly()}'s javadoc to
364 * see which fields fields "key".
365 * This allows quicker access to shortcut information in order to
366 * determine whether the caller's in-memory cache needs to be updated.
Makoto Onuki4a910962016-07-07 13:57:34 -0700367 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700368 * <p>Typically, launcher applications cache all or most shortcut information
369 * in memory in order to show shortcuts without a delay.
370 *
371 * When a given launcher application wants to update its cache, such as when its process
372 * restarts, it can fetch shortcut information with this flag.
373 * The application can then check {@link ShortcutInfo#getLastChangedTimestamp()} for each
374 * shortcut, fetching a shortcut's non-key information only if that shortcut has been
375 * updated.
Makoto Onuki4a910962016-07-07 13:57:34 -0700376 *
377 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800378 */
379 public static final int FLAG_GET_KEY_FIELDS_ONLY = 1 << 2;
380
381 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700382 @IntDef(flag = true, prefix = { "FLAG_" }, value = {
383 FLAG_MATCH_DYNAMIC,
384 FLAG_MATCH_PINNED,
385 FLAG_MATCH_MANIFEST,
386 FLAG_GET_KEY_FIELDS_ONLY,
387 FLAG_MATCH_MANIFEST,
388 })
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800389 @Retention(RetentionPolicy.SOURCE)
390 public @interface QueryFlags {}
391
392 long mChangedSince;
393
394 @Nullable
395 String mPackage;
396
397 @Nullable
Makoto Onukiabe84422016-04-07 09:41:19 -0700398 List<String> mShortcutIds;
399
400 @Nullable
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800401 ComponentName mActivity;
402
403 @QueryFlags
404 int mQueryFlags;
405
406 public ShortcutQuery() {
407 }
408
409 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700410 * If non-zero, returns only shortcuts that have been added or updated
411 * since the given timestamp, expressed in milliseconds since the Epoch&mdash;see
412 * {@link System#currentTimeMillis()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800413 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700414 public ShortcutQuery setChangedSince(long changedSince) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800415 mChangedSince = changedSince;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700416 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800417 }
418
419 /**
420 * If non-null, returns only shortcuts from the package.
421 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700422 public ShortcutQuery setPackage(@Nullable String packageName) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800423 mPackage = packageName;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700424 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800425 }
426
427 /**
Makoto Onukiabe84422016-04-07 09:41:19 -0700428 * If non-null, return only the specified shortcuts by ID. When setting this field,
Makoto Onuki4a910962016-07-07 13:57:34 -0700429 * a package name must also be set with {@link #setPackage}.
Makoto Onukiabe84422016-04-07 09:41:19 -0700430 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700431 public ShortcutQuery setShortcutIds(@Nullable List<String> shortcutIds) {
Makoto Onukiabe84422016-04-07 09:41:19 -0700432 mShortcutIds = shortcutIds;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700433 return this;
Makoto Onukiabe84422016-04-07 09:41:19 -0700434 }
435
436 /**
Makoto Onuki22fcc682016-05-17 14:52:19 -0700437 * If non-null, returns only shortcuts associated with the activity; i.e.
438 * {@link ShortcutInfo}s whose {@link ShortcutInfo#getActivity()} are equal
439 * to {@code activity}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800440 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700441 public ShortcutQuery setActivity(@Nullable ComponentName activity) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800442 mActivity = activity;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700443 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800444 }
445
Hakan Seyalioglu58fc95d2016-12-13 15:23:22 -0800446 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700447 * Set query options. At least one of the {@code MATCH} flags should be set. Otherwise,
448 * no shortcuts will be returned.
Makoto Onuki4a910962016-07-07 13:57:34 -0700449 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700450 * <ul>
451 * <li>{@link #FLAG_MATCH_DYNAMIC}
452 * <li>{@link #FLAG_MATCH_PINNED}
453 * <li>{@link #FLAG_MATCH_MANIFEST}
454 * <li>{@link #FLAG_GET_KEY_FIELDS_ONLY}
455 * </ul>
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800456 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700457 public ShortcutQuery setQueryFlags(@QueryFlags int queryFlags) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800458 mQueryFlags = queryFlags;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700459 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800460 }
Kenny Guyc01545372014-06-16 14:17:26 +0100461 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800462
Amith Yamasani4f582632014-02-19 14:31:52 -0800463 /** @hide */
464 public LauncherApps(Context context, ILauncherApps service) {
465 mContext = context;
466 mService = service;
Amith Yamasanie781c812014-05-28 15:28:18 -0700467 mPm = context.getPackageManager();
Makoto Onukide3c16c2017-01-26 11:39:31 -0800468 mUserManager = context.getSystemService(UserManager.class);
Amith Yamasani4f582632014-02-19 14:31:52 -0800469 }
470
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -0700471 /** @hide */
472 @TestApi
473 public LauncherApps(Context context) {
474 this(context, ILauncherApps.Stub.asInterface(
475 ServiceManager.getService(Context.LAUNCHER_APPS_SERVICE)));
476 }
477
Amith Yamasani4f582632014-02-19 14:31:52 -0800478 /**
Makoto Onukide3c16c2017-01-26 11:39:31 -0800479 * Show an error log on logcat, when the calling user is a managed profile, and the target
480 * user is different from the calling user, in order to help developers to detect it.
481 */
482 private void logErrorForInvalidProfileAccess(@NonNull UserHandle target) {
483 if (UserHandle.myUserId() != target.getIdentifier() && mUserManager.isManagedProfile()) {
Makoto Onuki3cc7cd12017-04-03 12:48:42 -0700484 Log.w(TAG, "Accessing other profiles/users from managed profile is no longer allowed.");
Makoto Onukide3c16c2017-01-26 11:39:31 -0800485 }
486 }
487
488 /**
Makoto Onukiaecbd032017-01-19 12:11:11 -0800489 * Return a list of profiles that the caller can access via the {@link LauncherApps} APIs.
490 *
491 * <p>If the caller is running on a managed profile, it'll return only the current profile.
492 * Otherwise it'll return the same list as {@link UserManager#getUserProfiles()} would.
493 */
494 public List<UserHandle> getProfiles() {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800495 if (mUserManager.isManagedProfile()) {
Makoto Onukiaecbd032017-01-19 12:11:11 -0800496 // If it's a managed profile, only return the current profile.
497 final List result = new ArrayList(1);
498 result.add(android.os.Process.myUserHandle());
499 return result;
500 } else {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800501 return mUserManager.getUserProfiles();
Makoto Onukiaecbd032017-01-19 12:11:11 -0800502 }
503 }
504
505 /**
Amith Yamasani4f582632014-02-19 14:31:52 -0800506 * Retrieves a list of launchable activities that match {@link Intent#ACTION_MAIN} and
Ricky Wai905908f2019-01-29 15:19:52 +0000507 * {@link Intent#CATEGORY_LAUNCHER}, for a specified user. Result may include
508 * synthesized activities like app details Activity injected by system.
Amith Yamasani4f582632014-02-19 14:31:52 -0800509 *
510 * @param packageName The specific package to query. If null, it checks all installed packages
511 * in the profile.
512 * @param user The UserHandle of the profile.
513 * @return List of launchable activities. Can be an empty list but will not be null.
514 */
515 public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800516 logErrorForInvalidProfileAccess(user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800517 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800518 return convertToActivityList(mService.getLauncherActivities(mContext.getPackageName(),
519 packageName, user), user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800520 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700521 throw re.rethrowFromSystemServer();
Amith Yamasani4f582632014-02-19 14:31:52 -0800522 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800523 }
524
Amith Yamasani4f582632014-02-19 14:31:52 -0800525 /**
526 * Returns the activity info for a given intent and user handle, if it resolves. Otherwise it
527 * returns null.
528 *
529 * @param intent The intent to find a match for.
530 * @param user The profile to look in for a match.
531 * @return An activity info object if there is a match.
532 */
533 public LauncherActivityInfo resolveActivity(Intent intent, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800534 logErrorForInvalidProfileAccess(user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800535 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800536 ActivityInfo ai = mService.resolveActivity(mContext.getPackageName(),
537 intent.getComponent(), user);
Sunny Goyal45d3e972016-03-31 12:38:17 -0700538 if (ai != null) {
539 LauncherActivityInfo info = new LauncherActivityInfo(mContext, ai, user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800540 return info;
541 }
542 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700543 throw re.rethrowFromSystemServer();
Amith Yamasani4f582632014-02-19 14:31:52 -0800544 }
545 return null;
546 }
547
548 /**
Kenny Guyf939dba2014-08-15 15:32:34 +0100549 * Starts a Main activity in the specified profile.
Amith Yamasani4f582632014-02-19 14:31:52 -0800550 *
551 * @param component The ComponentName of the activity to launch
Amith Yamasanie781c812014-05-28 15:28:18 -0700552 * @param user The UserHandle of the profile
553 * @param sourceBounds The Rect containing the source bounds of the clicked icon
554 * @param opts Options to pass to startActivity
555 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100556 public void startMainActivity(ComponentName component, UserHandle user, Rect sourceBounds,
Amith Yamasanie781c812014-05-28 15:28:18 -0700557 Bundle opts) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800558 logErrorForInvalidProfileAccess(user);
Amith Yamasani5abdbb62014-04-08 17:23:46 -0700559 if (DEBUG) {
Kenny Guyf939dba2014-08-15 15:32:34 +0100560 Log.i(TAG, "StartMainActivity " + component + " " + user.getIdentifier());
Amith Yamasani5abdbb62014-04-08 17:23:46 -0700561 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800562 try {
Makoto Onuki1a342742018-04-26 14:56:59 -0700563 mService.startActivityAsUser(mContext.getIApplicationThread(),
564 mContext.getPackageName(),
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800565 component, sourceBounds, opts, user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800566 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700567 throw re.rethrowFromSystemServer();
Amith Yamasani4f582632014-02-19 14:31:52 -0800568 }
569 }
570
571 /**
Jon Miranda2b340a22019-01-25 14:03:49 -0800572 * Starts an activity to show the details of the specified session.
573 *
574 * @param sessionInfo The SessionInfo of the session
575 * @param sourceBounds The Rect containing the source bounds of the clicked icon
576 * @param opts Options to pass to startActivity
577 */
Jon Miranda93505982019-03-08 09:33:42 -0800578 public void startPackageInstallerSessionDetailsActivity(@NonNull SessionInfo sessionInfo,
579 @Nullable Rect sourceBounds, @Nullable Bundle opts) {
Jon Miranda2b340a22019-01-25 14:03:49 -0800580 try {
581 mService.startSessionDetailsActivityAsUser(mContext.getIApplicationThread(),
582 mContext.getPackageName(), sessionInfo, sourceBounds, opts,
583 sessionInfo.getUser());
584 } catch (RemoteException re) {
585 throw re.rethrowFromSystemServer();
586 }
587 }
588
589 /**
Kenny Guy466d2032014-07-23 12:23:35 +0100590 * Starts the settings activity to show the application details for a
591 * package in the specified profile.
592 *
593 * @param component The ComponentName of the package to launch settings for.
594 * @param user The UserHandle of the profile
595 * @param sourceBounds The Rect containing the source bounds of the clicked icon
596 * @param opts Options to pass to startActivity
597 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100598 public void startAppDetailsActivity(ComponentName component, UserHandle user,
Kenny Guy466d2032014-07-23 12:23:35 +0100599 Rect sourceBounds, Bundle opts) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800600 logErrorForInvalidProfileAccess(user);
Kenny Guy466d2032014-07-23 12:23:35 +0100601 try {
Makoto Onuki1a342742018-04-26 14:56:59 -0700602 mService.showAppDetailsAsUser(mContext.getIApplicationThread(),
603 mContext.getPackageName(),
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800604 component, sourceBounds, opts, user);
Kenny Guy466d2032014-07-23 12:23:35 +0100605 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700606 throw re.rethrowFromSystemServer();
Kenny Guy466d2032014-07-23 12:23:35 +0100607 }
608 }
609
610 /**
Sunny Goyala6be88a2017-01-12 16:27:58 -0800611 * Retrieves a list of config activities for creating {@link ShortcutInfo}.
612 *
613 * @param packageName The specific package to query. If null, it checks all installed packages
614 * in the profile.
615 * @param user The UserHandle of the profile.
616 * @return List of config activities. Can be an empty list but will not be null.
617 *
618 * @see Intent#ACTION_CREATE_SHORTCUT
619 * @see #getShortcutConfigActivityIntent(LauncherActivityInfo)
620 */
621 public List<LauncherActivityInfo> getShortcutConfigActivityList(@Nullable String packageName,
622 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800623 logErrorForInvalidProfileAccess(user);
Sunny Goyala6be88a2017-01-12 16:27:58 -0800624 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800625 return convertToActivityList(mService.getShortcutConfigActivities(
626 mContext.getPackageName(), packageName, user),
Sunny Goyala6be88a2017-01-12 16:27:58 -0800627 user);
628 } catch (RemoteException re) {
629 throw re.rethrowFromSystemServer();
630 }
631 }
632
633 private List<LauncherActivityInfo> convertToActivityList(
634 @Nullable ParceledListSlice<ResolveInfo> activities, UserHandle user) {
635 if (activities == null) {
636 return Collections.EMPTY_LIST;
637 }
638 ArrayList<LauncherActivityInfo> lais = new ArrayList<>();
639 for (ResolveInfo ri : activities.getList()) {
640 LauncherActivityInfo lai = new LauncherActivityInfo(mContext, ri.activityInfo, user);
641 if (DEBUG) {
642 Log.v(TAG, "Returning activity for profile " + user + " : "
643 + lai.getComponentName());
644 }
645 lais.add(lai);
646 }
647 return lais;
648 }
649
650 /**
651 * Returns an intent sender which can be used to start the configure activity for creating
652 * custom shortcuts. Use this method if the provider is in another profile as you are not
653 * allowed to start an activity in another profile.
654 *
655 * <p>The caller should receive {@link PinItemRequest} in onActivityResult on
656 * {@link android.app.Activity#RESULT_OK}.
657 *
658 * <p>Callers must be allowed to access the shortcut information, as defined in {@link
659 * #hasShortcutHostPermission()}.
660 *
661 * @param info a configuration activity returned by {@link #getShortcutConfigActivityList}
662 *
663 * @throws IllegalStateException when the user is locked or not running.
664 * @throws SecurityException if {@link #hasShortcutHostPermission()} is false.
665 *
666 * @see #getPinItemRequest(Intent)
667 * @see Intent#ACTION_CREATE_SHORTCUT
668 * @see android.app.Activity#startIntentSenderForResult
669 */
Makoto Onukide3c16c2017-01-26 11:39:31 -0800670 @Nullable
Sunny Goyala6be88a2017-01-12 16:27:58 -0800671 public IntentSender getShortcutConfigActivityIntent(@NonNull LauncherActivityInfo info) {
672 try {
673 return mService.getShortcutConfigActivityIntent(
674 mContext.getPackageName(), info.getComponentName(), info.getUser());
675 } catch (RemoteException re) {
676 throw re.rethrowFromSystemServer();
677 }
678 }
679
680 /**
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100681 * Checks if the package is installed and enabled for a profile.
682 *
683 * @param packageName The package to check.
684 * @param user The UserHandle of the profile.
685 *
686 * @return true if the package exists and is enabled.
687 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100688 public boolean isPackageEnabled(String packageName, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800689 logErrorForInvalidProfileAccess(user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100690 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800691 return mService.isPackageEnabled(mContext.getPackageName(), packageName, user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100692 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700693 throw re.rethrowFromSystemServer();
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100694 }
695 }
696
697 /**
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700698 * Gets the launcher extras supplied to the system when the given package was suspended via
699 * {@code PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
700 * PersistableBundle, String)}.
701 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700702 * <p>The contents of this {@link Bundle} are supposed to be a contract between the suspending
703 * app and the launcher.
704 *
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700705 * <p>Note: This just returns whatever extras were provided to the system, <em>which might
706 * even be {@code null}.</em>
707 *
708 * @param packageName The package for which to fetch the launcher extras.
709 * @param user The {@link UserHandle} of the profile.
710 * @return A {@link Bundle} of launcher extras. Or {@code null} if the package is not currently
711 * suspended.
712 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700713 * @see Callback#onPackagesSuspended(String[], UserHandle, Bundle)
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700714 * @see PackageManager#isPackageSuspended()
715 */
716 public @Nullable Bundle getSuspendedPackageLauncherExtras(String packageName, UserHandle user) {
717 logErrorForInvalidProfileAccess(user);
718 try {
719 return mService.getSuspendedPackageLauncherExtras(packageName, user);
720 } catch (RemoteException re) {
721 throw re.rethrowFromSystemServer();
722 }
723 }
724
725 /**
Suprabh Shukla79000492018-12-24 17:03:02 -0800726 * Returns whether a package should be hidden from suggestions to the user. Currently, this
727 * could be done because the package was marked as distracting to the user via
728 * {@code PackageManager.setDistractingPackageRestrictions(String[], int)}.
729 *
730 * @param packageName The package for which to check.
731 * @param user the {@link UserHandle} of the profile.
732 * @return
733 */
734 public boolean shouldHideFromSuggestions(@NonNull String packageName,
735 @NonNull UserHandle user) {
736 Preconditions.checkNotNull(packageName, "packageName");
737 Preconditions.checkNotNull(user, "user");
738 try {
739 return mService.shouldHideFromSuggestions(packageName, user);
740 } catch (RemoteException re) {
741 throw re.rethrowFromSystemServer();
742 }
743 }
744
745 /**
Benjamin Miller7afa84c2017-07-17 13:01:35 +0200746 * Returns {@link ApplicationInfo} about an application installed for a specific user profile.
Kenny Guy77242752016-01-15 13:29:06 +0000747 *
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700748 * @param packageName The package name of the application
Kenny Guy77242752016-01-15 13:29:06 +0000749 * @param flags Additional option flags {@link PackageManager#getApplicationInfo}
750 * @param user The UserHandle of the profile.
751 *
Benjamin Miller7afa84c2017-07-17 13:01:35 +0200752 * @return {@link ApplicationInfo} containing information about the package. Returns
753 * {@code null} if the package isn't installed for the given profile, or the profile
754 * isn't enabled.
Kenny Guy77242752016-01-15 13:29:06 +0000755 */
Makoto Onuki7c7fbf62017-04-14 11:03:56 -0700756 public ApplicationInfo getApplicationInfo(@NonNull String packageName,
757 @ApplicationInfoFlags int flags, @NonNull UserHandle user)
758 throws PackageManager.NameNotFoundException {
759 Preconditions.checkNotNull(packageName, "packageName");
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700760 Preconditions.checkNotNull(user, "user");
Makoto Onukide3c16c2017-01-26 11:39:31 -0800761 logErrorForInvalidProfileAccess(user);
Kenny Guy77242752016-01-15 13:29:06 +0000762 try {
Makoto Onuki7c7fbf62017-04-14 11:03:56 -0700763 final ApplicationInfo ai = mService
764 .getApplicationInfo(mContext.getPackageName(), packageName, flags, user);
765 if (ai == null) {
766 throw new NameNotFoundException("Package " + packageName + " not found for user "
767 + user.getIdentifier());
768 }
769 return ai;
Kenny Guy77242752016-01-15 13:29:06 +0000770 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700771 throw re.rethrowFromSystemServer();
Kenny Guy77242752016-01-15 13:29:06 +0000772 }
773 }
774
775 /**
Varun Shah2546cef2019-01-11 15:50:54 -0800776 * Returns an object describing the app usage limit for the given package.
777 * If there are multiple limits that apply to the package, the one with the smallest
778 * time remaining will be returned.
779 *
780 * @param packageName name of the package whose app usage limit will be returned
781 * @param user the user of the package
782 *
783 * @return an {@link AppUsageLimit} object describing the app time limit containing
784 * the given package with the smallest time remaining, or {@code null} if none exist.
Varun Shahe9abb752019-02-11 11:25:06 -0800785 * @throws SecurityException when the caller is not the recents app.
Sunny Goyalbeee1972019-03-29 11:38:16 -0700786 * @hide
Varun Shah2546cef2019-01-11 15:50:54 -0800787 */
788 @Nullable
Sunny Goyalbeee1972019-03-29 11:38:16 -0700789 @SystemApi
Varun Shah2c9263c2019-02-15 10:51:10 -0800790 public LauncherApps.AppUsageLimit getAppUsageLimit(@NonNull String packageName,
791 @NonNull UserHandle user) {
Varun Shah2546cef2019-01-11 15:50:54 -0800792 try {
793 return mService.getAppUsageLimit(mContext.getPackageName(), packageName, user);
794 } catch (RemoteException re) {
795 throw re.rethrowFromSystemServer();
796 }
797 }
798
799 /**
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100800 * Checks if the activity exists and it enabled for a profile.
801 *
Makoto Onuki516020a2019-01-28 14:16:42 -0800802 * <p>The activity may still not be exported, in which case {@link #startMainActivity} will
803 * throw a {@link SecurityException} unless the caller has the same UID as the target app's.
804 *
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100805 * @param component The activity to check.
806 * @param user The UserHandle of the profile.
807 *
808 * @return true if the activity exists and is enabled.
809 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100810 public boolean isActivityEnabled(ComponentName component, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800811 logErrorForInvalidProfileAccess(user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100812 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800813 return mService.isActivityEnabled(mContext.getPackageName(), component, user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100814 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700815 throw re.rethrowFromSystemServer();
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100816 }
817 }
818
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800819 /**
Dianne Hackbornc160fa42017-11-01 16:14:26 -0700820 * Returns whether the caller can access the shortcut information. Access is currently
821 * available to:
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800822 *
Dianne Hackbornc160fa42017-11-01 16:14:26 -0700823 * <ul>
824 * <li>The current launcher (or default launcher if there is no set current launcher).</li>
825 * <li>The currently active voice interaction service.</li>
826 * </ul>
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800827 *
Makoto Onuki4a910962016-07-07 13:57:34 -0700828 * <p>Note when this method returns {@code false}, it may be a temporary situation because
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800829 * the user is trying a new launcher application. The user may decide to change the default
Makoto Onuki4a910962016-07-07 13:57:34 -0700830 * launcher back to the calling application again, so even if a launcher application loses
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800831 * this permission, it does <b>not</b> have to purge pinned shortcut information.
Makoto Onukife9c9662016-07-25 15:12:23 -0700832 * If the calling launcher application contains pinned shortcuts, they will still work,
833 * even though the caller no longer has the shortcut host permission.
Makoto Onuki4a910962016-07-07 13:57:34 -0700834 *
Makoto Onuki02f338e2016-07-29 09:40:40 -0700835 * @throws IllegalStateException when the user is locked.
Makoto Onuki9c850012016-07-26 15:50:50 -0700836 *
Makoto Onuki4a910962016-07-07 13:57:34 -0700837 * @see ShortcutManager
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800838 */
839 public boolean hasShortcutHostPermission() {
840 try {
841 return mService.hasShortcutHostPermission(mContext.getPackageName());
842 } catch (RemoteException re) {
843 throw re.rethrowFromSystemServer();
844 }
845 }
846
Makoto Onukib1588c02017-10-12 15:11:45 -0700847 private List<ShortcutInfo> maybeUpdateDisabledMessage(List<ShortcutInfo> shortcuts) {
848 if (shortcuts == null) {
849 return null;
850 }
851 for (int i = shortcuts.size() - 1; i >= 0; i--) {
852 final ShortcutInfo si = shortcuts.get(i);
853 final String message = ShortcutInfo.getDisabledReasonForRestoreIssue(mContext,
854 si.getDisabledReason());
855 if (message != null) {
856 si.setDisabledMessage(message);
857 }
858 }
859 return shortcuts;
860 }
861
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800862 /**
Makoto Onuki4a910962016-07-07 13:57:34 -0700863 * Returns {@link ShortcutInfo}s that match {@code query}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800864 *
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800865 * <p>Callers must be allowed to access the shortcut information, as defined in {@link
866 * #hasShortcutHostPermission()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800867 *
868 * @param query result includes shortcuts matching this query.
869 * @param user The UserHandle of the profile.
870 *
871 * @return the IDs of {@link ShortcutInfo}s that match the query.
Makoto Onuki02f338e2016-07-29 09:40:40 -0700872 * @throws IllegalStateException when the user is locked, or when the {@code user} user
873 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -0700874 *
875 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800876 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800877 @Nullable
878 public List<ShortcutInfo> getShortcuts(@NonNull ShortcutQuery query,
879 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800880 logErrorForInvalidProfileAccess(user);
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800881 try {
Makoto Onukib1588c02017-10-12 15:11:45 -0700882 // Note this is the only case we need to update the disabled message for shortcuts
883 // that weren't restored.
884 // The restore problem messages are only shown by the user, and publishers will never
885 // see them. The only other API that the launcher gets shortcuts is the shortcut
886 // changed callback, but that only returns shortcuts with the "key" information, so
887 // that won't return disabled message.
888 return maybeUpdateDisabledMessage(mService.getShortcuts(mContext.getPackageName(),
Makoto Onukiabe84422016-04-07 09:41:19 -0700889 query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
Makoto Onuki99302b52017-03-29 12:42:26 -0700890 query.mQueryFlags, user)
Makoto Onukib1588c02017-10-12 15:11:45 -0700891 .getList());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800892 } catch (RemoteException e) {
893 throw e.rethrowFromSystemServer();
894 }
895 }
896
897 /**
Makoto Onukiabe84422016-04-07 09:41:19 -0700898 * @hide // No longer used. Use getShortcuts() instead. Kept for unit tests.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800899 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800900 @Nullable
Makoto Onukib5a012f2016-06-21 11:13:53 -0700901 @Deprecated
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800902 public List<ShortcutInfo> getShortcutInfo(@NonNull String packageName,
903 @NonNull List<String> ids, @NonNull UserHandle user) {
Makoto Onukiabe84422016-04-07 09:41:19 -0700904 final ShortcutQuery q = new ShortcutQuery();
905 q.setPackage(packageName);
906 q.setShortcutIds(ids);
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700907 q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
Makoto Onukiabe84422016-04-07 09:41:19 -0700908 return getShortcuts(q, user);
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800909 }
910
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800911 /**
912 * Pin shortcuts on a package.
913 *
914 * <p>This API is <b>NOT</b> cumulative; this will replace all pinned shortcuts for the package.
915 * However, different launchers may have different set of pinned shortcuts.
916 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700917 * <p>The calling launcher application must be allowed to access the shortcut information,
918 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800919 *
920 * @param packageName The target package name.
921 * @param shortcutIds The IDs of the shortcut to be pinned.
922 * @param user The UserHandle of the profile.
Makoto Onuki02f338e2016-07-29 09:40:40 -0700923 * @throws IllegalStateException when the user is locked, or when the {@code user} user
924 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -0700925 *
926 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800927 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800928 public void pinShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
929 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800930 logErrorForInvalidProfileAccess(user);
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800931 try {
932 mService.pinShortcuts(mContext.getPackageName(), packageName, shortcutIds, user);
933 } catch (RemoteException e) {
934 throw e.rethrowFromSystemServer();
935 }
936 }
937
938 /**
Makoto Onukib6d35232016-04-04 15:57:17 -0700939 * @hide kept for testing.
Makoto Onukiabe84422016-04-07 09:41:19 -0700940 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700941 @Deprecated
Makoto Onukiabe84422016-04-07 09:41:19 -0700942 public int getShortcutIconResId(@NonNull ShortcutInfo shortcut) {
Makoto Onukib6d35232016-04-04 15:57:17 -0700943 return shortcut.getIconResourceId();
Makoto Onukiabe84422016-04-07 09:41:19 -0700944 }
945
946 /**
Makoto Onukib6d35232016-04-04 15:57:17 -0700947 * @hide kept for testing.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800948 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700949 @Deprecated
Makoto Onukiabe84422016-04-07 09:41:19 -0700950 public int getShortcutIconResId(@NonNull String packageName, @NonNull String shortcutId,
951 @NonNull UserHandle user) {
Makoto Onukib6d35232016-04-04 15:57:17 -0700952 final ShortcutQuery q = new ShortcutQuery();
953 q.setPackage(packageName);
954 q.setShortcutIds(Arrays.asList(shortcutId));
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700955 q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
Makoto Onukib6d35232016-04-04 15:57:17 -0700956 final List<ShortcutInfo> shortcuts = getShortcuts(q, user);
Makoto Onukiabe84422016-04-07 09:41:19 -0700957
Makoto Onukib6d35232016-04-04 15:57:17 -0700958 return shortcuts.size() > 0 ? shortcuts.get(0).getIconResourceId() : 0;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800959 }
960
961 /**
Makoto Onukib5a012f2016-06-21 11:13:53 -0700962 * @hide internal/unit tests only
Makoto Onukiabe84422016-04-07 09:41:19 -0700963 */
964 public ParcelFileDescriptor getShortcutIconFd(
965 @NonNull ShortcutInfo shortcut) {
Makoto Onuki22fcc682016-05-17 14:52:19 -0700966 return getShortcutIconFd(shortcut.getPackage(), shortcut.getId(),
Makoto Onukiabe84422016-04-07 09:41:19 -0700967 shortcut.getUserId());
968 }
969
970 /**
Makoto Onukib5a012f2016-06-21 11:13:53 -0700971 * @hide internal/unit tests only
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800972 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800973 public ParcelFileDescriptor getShortcutIconFd(
Makoto Onukiabe84422016-04-07 09:41:19 -0700974 @NonNull String packageName, @NonNull String shortcutId, @NonNull UserHandle user) {
975 return getShortcutIconFd(packageName, shortcutId, user.getIdentifier());
976 }
977
978 private ParcelFileDescriptor getShortcutIconFd(
979 @NonNull String packageName, @NonNull String shortcutId, int userId) {
Makoto Onuki55046222016-03-08 10:49:47 -0800980 try {
Makoto Onukiabe84422016-04-07 09:41:19 -0700981 return mService.getShortcutIconFd(mContext.getPackageName(),
982 packageName, shortcutId, userId);
Makoto Onuki55046222016-03-08 10:49:47 -0800983 } catch (RemoteException e) {
984 throw e.rethrowFromSystemServer();
985 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800986 }
987
Makoto Onuki04b9aab2016-05-23 17:13:30 -0700988 /**
989 * Returns the icon for this shortcut, without any badging for the profile.
990 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700991 * <p>The calling launcher application must be allowed to access the shortcut information,
992 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki4a910962016-07-07 13:57:34 -0700993 *
Makoto Onuki04b9aab2016-05-23 17:13:30 -0700994 * @param density The preferred density of the icon, zero for default density. Use
995 * density DPI values from {@link DisplayMetrics}.
Makoto Onuki4a910962016-07-07 13:57:34 -0700996 *
997 * @return The drawable associated with the shortcut.
Makoto Onuki02f338e2016-07-29 09:40:40 -0700998 * @throws IllegalStateException when the user is locked, or when the {@code user} user
999 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -07001000 *
1001 * @see ShortcutManager
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001002 * @see #getShortcutBadgedIconDrawable(ShortcutInfo, int)
1003 * @see DisplayMetrics
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001004 */
1005 public Drawable getShortcutIconDrawable(@NonNull ShortcutInfo shortcut, int density) {
1006 if (shortcut.hasIconFile()) {
1007 final ParcelFileDescriptor pfd = getShortcutIconFd(shortcut);
1008 if (pfd == null) {
1009 return null;
1010 }
1011 try {
1012 final Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
Hyunyoung Songf281e7a2017-02-13 10:57:42 -08001013 if (bmp != null) {
1014 BitmapDrawable dr = new BitmapDrawable(mContext.getResources(), bmp);
Hyunyoung Songe4179e22017-03-01 12:51:26 -08001015 if (shortcut.hasAdaptiveBitmap()) {
Hyunyoung Songbe8835e2017-02-17 11:25:08 -08001016 return new AdaptiveIconDrawable(null, dr);
Hyunyoung Songf281e7a2017-02-13 10:57:42 -08001017 } else {
1018 return dr;
1019 }
1020 }
1021 return null;
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001022 } finally {
1023 try {
1024 pfd.close();
1025 } catch (IOException ignore) {
1026 }
1027 }
1028 } else if (shortcut.hasIconResource()) {
Makoto Onuki2d895c32016-12-02 15:48:40 -08001029 return loadDrawableResourceFromPackage(shortcut.getPackage(),
1030 shortcut.getIconResourceId(), shortcut.getUserHandle(), density);
1031 } else if (shortcut.getIcon() != null) {
1032 // This happens if a shortcut is pending-approval.
1033 final Icon icon = shortcut.getIcon();
1034 switch (icon.getType()) {
1035 case Icon.TYPE_RESOURCE: {
1036 return loadDrawableResourceFromPackage(shortcut.getPackage(),
1037 icon.getResId(), shortcut.getUserHandle(), density);
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001038 }
Hyunyoung Songf281e7a2017-02-13 10:57:42 -08001039 case Icon.TYPE_BITMAP:
Hyunyoung Songe4179e22017-03-01 12:51:26 -08001040 case Icon.TYPE_ADAPTIVE_BITMAP: {
Makoto Onuki2d895c32016-12-02 15:48:40 -08001041 return icon.loadDrawable(mContext);
1042 }
1043 default:
1044 return null; // Shouldn't happen though.
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001045 }
1046 } else {
1047 return null; // Has no icon.
1048 }
Makoto Onuki20c95f82016-05-11 16:51:01 -07001049 }
1050
Makoto Onuki2d895c32016-12-02 15:48:40 -08001051 private Drawable loadDrawableResourceFromPackage(String packageName, int resId,
1052 UserHandle user, int density) {
1053 try {
1054 if (resId == 0) {
1055 return null; // Shouldn't happen but just in case.
1056 }
1057 final ApplicationInfo ai = getApplicationInfo(packageName, /* flags =*/ 0, user);
1058 final Resources res = mContext.getPackageManager().getResourcesForApplication(ai);
1059 return res.getDrawableForDensity(resId, density);
1060 } catch (NameNotFoundException | Resources.NotFoundException e) {
1061 return null;
1062 }
1063 }
1064
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001065 /**
1066 * Returns the shortcut icon with badging appropriate for the profile.
1067 *
Makoto Onukife9c9662016-07-25 15:12:23 -07001068 * <p>The calling launcher application must be allowed to access the shortcut information,
1069 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki4a910962016-07-07 13:57:34 -07001070 *
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001071 * @param density Optional density for the icon, or 0 to use the default density. Use
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001072 * @return A badged icon for the shortcut.
Makoto Onuki02f338e2016-07-29 09:40:40 -07001073 * @throws IllegalStateException when the user is locked, or when the {@code user} user
1074 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -07001075 *
1076 * @see ShortcutManager
Makoto Onukife9c9662016-07-25 15:12:23 -07001077 * @see #getShortcutIconDrawable(ShortcutInfo, int)
Makoto Onuki4a910962016-07-07 13:57:34 -07001078 * @see DisplayMetrics
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001079 */
1080 public Drawable getShortcutBadgedIconDrawable(ShortcutInfo shortcut, int density) {
1081 final Drawable originalIcon = getShortcutIconDrawable(shortcut, density);
1082
1083 return (originalIcon == null) ? null : mContext.getPackageManager().getUserBadgedIcon(
1084 originalIcon, shortcut.getUserHandle());
Makoto Onuki20c95f82016-05-11 16:51:01 -07001085 }
1086
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001087 /**
Makoto Onuki4a910962016-07-07 13:57:34 -07001088 * Starts a shortcut.
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001089 *
Makoto Onukife9c9662016-07-25 15:12:23 -07001090 * <p>The calling launcher application must be allowed to access the shortcut information,
1091 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001092 *
Makoto Onuki43204b82016-03-08 16:16:44 -08001093 * @param packageName The target shortcut package name.
1094 * @param shortcutId The target shortcut ID.
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001095 * @param sourceBounds The Rect containing the source bounds of the clicked icon.
1096 * @param startActivityOptions Options to pass to startActivity.
1097 * @param user The UserHandle of the profile.
Makoto Onuki02f338e2016-07-29 09:40:40 -07001098 * @throws IllegalStateException when the user is locked, or when the {@code user} user
1099 * is locked or not running.
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001100 *
1101 * @throws android.content.ActivityNotFoundException failed to start shortcut. (e.g.
1102 * the shortcut no longer exists, is disabled, the intent receiver activity doesn't exist, etc)
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001103 */
Makoto Onukid6880792016-06-29 13:37:43 -07001104 public void startShortcut(@NonNull String packageName, @NonNull String shortcutId,
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001105 @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
1106 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -08001107 logErrorForInvalidProfileAccess(user);
1108
Makoto Onukid6880792016-06-29 13:37:43 -07001109 startShortcut(packageName, shortcutId, sourceBounds, startActivityOptions,
Makoto Onukiabe84422016-04-07 09:41:19 -07001110 user.getIdentifier());
1111 }
1112
1113 /**
1114 * Launches a shortcut.
1115 *
Makoto Onukife9c9662016-07-25 15:12:23 -07001116 * <p>The calling launcher application must be allowed to access the shortcut information,
1117 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onukiabe84422016-04-07 09:41:19 -07001118 *
1119 * @param shortcut The target shortcut.
1120 * @param sourceBounds The Rect containing the source bounds of the clicked icon.
1121 * @param startActivityOptions Options to pass to startActivity.
Makoto Onuki02f338e2016-07-29 09:40:40 -07001122 * @throws IllegalStateException when the user is locked, or when the {@code user} user
1123 * is locked or not running.
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001124 *
1125 * @throws android.content.ActivityNotFoundException failed to start shortcut. (e.g.
1126 * the shortcut no longer exists, is disabled, the intent receiver activity doesn't exist, etc)
Makoto Onukiabe84422016-04-07 09:41:19 -07001127 */
Makoto Onukid6880792016-06-29 13:37:43 -07001128 public void startShortcut(@NonNull ShortcutInfo shortcut,
Makoto Onukiabe84422016-04-07 09:41:19 -07001129 @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions) {
Makoto Onukid6880792016-06-29 13:37:43 -07001130 startShortcut(shortcut.getPackage(), shortcut.getId(),
Makoto Onukiabe84422016-04-07 09:41:19 -07001131 sourceBounds, startActivityOptions,
1132 shortcut.getUserId());
1133 }
1134
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001135 @UnsupportedAppUsage
Makoto Onukid6880792016-06-29 13:37:43 -07001136 private void startShortcut(@NonNull String packageName, @NonNull String shortcutId,
Makoto Onukiabe84422016-04-07 09:41:19 -07001137 @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
1138 int userId) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001139 try {
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001140 final boolean success =
1141 mService.startShortcut(mContext.getPackageName(), packageName, shortcutId,
Makoto Onukiabe84422016-04-07 09:41:19 -07001142 sourceBounds, startActivityOptions, userId);
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001143 if (!success) {
1144 throw new ActivityNotFoundException("Shortcut could not be started");
1145 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001146 } catch (RemoteException e) {
1147 throw e.rethrowFromSystemServer();
1148 }
1149 }
Kenny Guy53fa4ec2014-04-29 14:24:18 +01001150
1151 /**
Jon Miranda2b340a22019-01-25 14:03:49 -08001152 * Registers a callback for changes to packages in this user and managed profiles.
Kenny Guyc01545372014-06-16 14:17:26 +01001153 *
Kenny Guy10a574f2014-08-26 16:17:58 +01001154 * @param callback The callback to register.
Kenny Guyc01545372014-06-16 14:17:26 +01001155 */
Kenny Guy10a574f2014-08-26 16:17:58 +01001156 public void registerCallback(Callback callback) {
1157 registerCallback(callback, null);
Kenny Guyb42c89b2014-07-28 19:20:07 +01001158 }
1159
1160 /**
Jon Miranda2b340a22019-01-25 14:03:49 -08001161 * Registers a callback for changes to packages in this user and managed profiles.
Kenny Guyb42c89b2014-07-28 19:20:07 +01001162 *
Kenny Guy10a574f2014-08-26 16:17:58 +01001163 * @param callback The callback to register.
Kenny Guyb42c89b2014-07-28 19:20:07 +01001164 * @param handler that should be used to post callbacks on, may be null.
1165 */
Kenny Guy10a574f2014-08-26 16:17:58 +01001166 public void registerCallback(Callback callback, Handler handler) {
Kenny Guyc01545372014-06-16 14:17:26 +01001167 synchronized (this) {
Kenny Guy172a2162015-06-19 17:21:28 +01001168 if (callback != null && findCallbackLocked(callback) < 0) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001169 boolean addedFirstCallback = mCallbacks.size() == 0;
1170 addCallbackLocked(callback, handler);
1171 if (addedFirstCallback) {
Kenny Guyc01545372014-06-16 14:17:26 +01001172 try {
Makoto Onuki4dbe0de2016-03-14 17:31:49 -07001173 mService.addOnAppsChangedListener(mContext.getPackageName(),
1174 mAppsChangedListener);
Kenny Guyc01545372014-06-16 14:17:26 +01001175 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001176 throw re.rethrowFromSystemServer();
Kenny Guyc01545372014-06-16 14:17:26 +01001177 }
1178 }
1179 }
1180 }
1181 }
1182
1183 /**
Kenny Guy10a574f2014-08-26 16:17:58 +01001184 * Unregisters a callback that was previously registered.
Kenny Guyc01545372014-06-16 14:17:26 +01001185 *
Kenny Guy10a574f2014-08-26 16:17:58 +01001186 * @param callback The callback to unregister.
1187 * @see #registerCallback(Callback)
Kenny Guyc01545372014-06-16 14:17:26 +01001188 */
Kenny Guy10a574f2014-08-26 16:17:58 +01001189 public void unregisterCallback(Callback callback) {
Kenny Guyc01545372014-06-16 14:17:26 +01001190 synchronized (this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001191 removeCallbackLocked(callback);
Kenny Guy44b6dee2014-07-10 18:10:14 +01001192 if (mCallbacks.size() == 0) {
Amith Yamasanie781c812014-05-28 15:28:18 -07001193 try {
1194 mService.removeOnAppsChangedListener(mAppsChangedListener);
1195 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001196 throw re.rethrowFromSystemServer();
Amith Yamasanie781c812014-05-28 15:28:18 -07001197 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001198 }
1199 }
1200 }
1201
Kenny Guy172a2162015-06-19 17:21:28 +01001202 /** @return position in mCallbacks for callback or -1 if not present. */
1203 private int findCallbackLocked(Callback callback) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001204 if (callback == null) {
1205 throw new IllegalArgumentException("Callback cannot be null");
1206 }
1207 final int size = mCallbacks.size();
1208 for (int i = 0; i < size; ++i) {
1209 if (mCallbacks.get(i).mCallback == callback) {
Kenny Guy172a2162015-06-19 17:21:28 +01001210 return i;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001211 }
1212 }
Kenny Guy172a2162015-06-19 17:21:28 +01001213 return -1;
1214 }
1215
1216 private void removeCallbackLocked(Callback callback) {
1217 int pos = findCallbackLocked(callback);
1218 if (pos >= 0) {
1219 mCallbacks.remove(pos);
1220 }
Kenny Guyb42c89b2014-07-28 19:20:07 +01001221 }
1222
Kenny Guyf939dba2014-08-15 15:32:34 +01001223 private void addCallbackLocked(Callback callback, Handler handler) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001224 // Remove if already present.
1225 removeCallbackLocked(callback);
1226 if (handler == null) {
1227 handler = new Handler();
1228 }
1229 CallbackMessageHandler toAdd = new CallbackMessageHandler(handler.getLooper(), callback);
1230 mCallbacks.add(toAdd);
1231 }
1232
Amith Yamasani4f582632014-02-19 14:31:52 -08001233 private IOnAppsChangedListener.Stub mAppsChangedListener = new IOnAppsChangedListener.Stub() {
1234
1235 @Override
Kenny Guyb42c89b2014-07-28 19:20:07 +01001236 public void onPackageRemoved(UserHandle user, String packageName)
1237 throws RemoteException {
Amith Yamasani4f582632014-02-19 14:31:52 -08001238 if (DEBUG) {
1239 Log.d(TAG, "onPackageRemoved " + user.getIdentifier() + "," + packageName);
1240 }
1241 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001242 for (CallbackMessageHandler callback : mCallbacks) {
1243 callback.postOnPackageRemoved(packageName, user);
Kenny Guyc01545372014-06-16 14:17:26 +01001244 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001245 }
1246 }
1247
1248 @Override
1249 public void onPackageChanged(UserHandle user, String packageName) throws RemoteException {
1250 if (DEBUG) {
1251 Log.d(TAG, "onPackageChanged " + user.getIdentifier() + "," + packageName);
1252 }
1253 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001254 for (CallbackMessageHandler callback : mCallbacks) {
1255 callback.postOnPackageChanged(packageName, user);
Kenny Guyc01545372014-06-16 14:17:26 +01001256 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001257 }
1258 }
1259
1260 @Override
1261 public void onPackageAdded(UserHandle user, String packageName) throws RemoteException {
1262 if (DEBUG) {
1263 Log.d(TAG, "onPackageAdded " + user.getIdentifier() + "," + packageName);
1264 }
1265 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001266 for (CallbackMessageHandler callback : mCallbacks) {
1267 callback.postOnPackageAdded(packageName, user);
Kenny Guyc01545372014-06-16 14:17:26 +01001268 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001269 }
1270 }
1271
1272 @Override
1273 public void onPackagesAvailable(UserHandle user, String[] packageNames, boolean replacing)
1274 throws RemoteException {
1275 if (DEBUG) {
1276 Log.d(TAG, "onPackagesAvailable " + user.getIdentifier() + "," + packageNames);
1277 }
1278 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001279 for (CallbackMessageHandler callback : mCallbacks) {
1280 callback.postOnPackagesAvailable(packageNames, user, replacing);
Kenny Guyc01545372014-06-16 14:17:26 +01001281 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001282 }
1283 }
1284
1285 @Override
1286 public void onPackagesUnavailable(UserHandle user, String[] packageNames, boolean replacing)
1287 throws RemoteException {
1288 if (DEBUG) {
1289 Log.d(TAG, "onPackagesUnavailable " + user.getIdentifier() + "," + packageNames);
1290 }
1291 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001292 for (CallbackMessageHandler callback : mCallbacks) {
1293 callback.postOnPackagesUnavailable(packageNames, user, replacing);
Kenny Guyc01545372014-06-16 14:17:26 +01001294 }
Kenny Guy77242752016-01-15 13:29:06 +00001295 }
1296 }
1297
1298 @Override
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001299 public void onPackagesSuspended(UserHandle user, String[] packageNames,
1300 Bundle launcherExtras)
Kenny Guy77242752016-01-15 13:29:06 +00001301 throws RemoteException {
1302 if (DEBUG) {
1303 Log.d(TAG, "onPackagesSuspended " + user.getIdentifier() + "," + packageNames);
1304 }
1305 synchronized (LauncherApps.this) {
1306 for (CallbackMessageHandler callback : mCallbacks) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001307 callback.postOnPackagesSuspended(packageNames, launcherExtras, user);
Kenny Guy77242752016-01-15 13:29:06 +00001308 }
1309 }
1310 }
1311
1312 @Override
1313 public void onPackagesUnsuspended(UserHandle user, String[] packageNames)
1314 throws RemoteException {
1315 if (DEBUG) {
1316 Log.d(TAG, "onPackagesUnsuspended " + user.getIdentifier() + "," + packageNames);
1317 }
1318 synchronized (LauncherApps.this) {
1319 for (CallbackMessageHandler callback : mCallbacks) {
1320 callback.postOnPackagesUnsuspended(packageNames, user);
1321 }
1322 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001323 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001324
1325 @Override
1326 public void onShortcutChanged(UserHandle user, String packageName,
1327 ParceledListSlice shortcuts) {
1328 if (DEBUG) {
1329 Log.d(TAG, "onShortcutChanged " + user.getIdentifier() + "," + packageName);
1330 }
1331 final List<ShortcutInfo> list = shortcuts.getList();
1332 synchronized (LauncherApps.this) {
1333 for (CallbackMessageHandler callback : mCallbacks) {
1334 callback.postOnShortcutChanged(packageName, user, list);
1335 }
1336 }
1337 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001338 };
Kenny Guyb42c89b2014-07-28 19:20:07 +01001339
1340 private static class CallbackMessageHandler extends Handler {
1341 private static final int MSG_ADDED = 1;
1342 private static final int MSG_REMOVED = 2;
1343 private static final int MSG_CHANGED = 3;
1344 private static final int MSG_AVAILABLE = 4;
1345 private static final int MSG_UNAVAILABLE = 5;
Kenny Guy77242752016-01-15 13:29:06 +00001346 private static final int MSG_SUSPENDED = 6;
1347 private static final int MSG_UNSUSPENDED = 7;
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001348 private static final int MSG_SHORTCUT_CHANGED = 8;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001349
Kenny Guyf939dba2014-08-15 15:32:34 +01001350 private LauncherApps.Callback mCallback;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001351
1352 private static class CallbackInfo {
1353 String[] packageNames;
1354 String packageName;
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001355 Bundle launcherExtras;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001356 boolean replacing;
1357 UserHandle user;
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001358 List<ShortcutInfo> shortcuts;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001359 }
1360
Kenny Guyf939dba2014-08-15 15:32:34 +01001361 public CallbackMessageHandler(Looper looper, LauncherApps.Callback callback) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001362 super(looper, null, true);
1363 mCallback = callback;
1364 }
1365
1366 @Override
1367 public void handleMessage(Message msg) {
1368 if (mCallback == null || !(msg.obj instanceof CallbackInfo)) {
1369 return;
1370 }
1371 CallbackInfo info = (CallbackInfo) msg.obj;
1372 switch (msg.what) {
1373 case MSG_ADDED:
1374 mCallback.onPackageAdded(info.packageName, info.user);
1375 break;
1376 case MSG_REMOVED:
1377 mCallback.onPackageRemoved(info.packageName, info.user);
1378 break;
1379 case MSG_CHANGED:
1380 mCallback.onPackageChanged(info.packageName, info.user);
1381 break;
1382 case MSG_AVAILABLE:
1383 mCallback.onPackagesAvailable(info.packageNames, info.user, info.replacing);
1384 break;
1385 case MSG_UNAVAILABLE:
1386 mCallback.onPackagesUnavailable(info.packageNames, info.user, info.replacing);
1387 break;
Kenny Guy77242752016-01-15 13:29:06 +00001388 case MSG_SUSPENDED:
Suprabh Shukla96212bc2018-04-10 15:04:51 -07001389 mCallback.onPackagesSuspended(info.packageNames, info.user, info.launcherExtras
1390 );
Kenny Guy77242752016-01-15 13:29:06 +00001391 break;
1392 case MSG_UNSUSPENDED:
1393 mCallback.onPackagesUnsuspended(info.packageNames, info.user);
1394 break;
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001395 case MSG_SHORTCUT_CHANGED:
1396 mCallback.onShortcutsChanged(info.packageName, info.shortcuts, info.user);
1397 break;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001398 }
1399 }
1400
1401 public void postOnPackageAdded(String packageName, UserHandle user) {
1402 CallbackInfo info = new CallbackInfo();
1403 info.packageName = packageName;
1404 info.user = user;
1405 obtainMessage(MSG_ADDED, info).sendToTarget();
1406 }
1407
1408 public void postOnPackageRemoved(String packageName, UserHandle user) {
1409 CallbackInfo info = new CallbackInfo();
1410 info.packageName = packageName;
1411 info.user = user;
1412 obtainMessage(MSG_REMOVED, info).sendToTarget();
1413 }
1414
1415 public void postOnPackageChanged(String packageName, UserHandle user) {
1416 CallbackInfo info = new CallbackInfo();
1417 info.packageName = packageName;
1418 info.user = user;
1419 obtainMessage(MSG_CHANGED, info).sendToTarget();
1420 }
1421
1422 public void postOnPackagesAvailable(String[] packageNames, UserHandle user,
1423 boolean replacing) {
1424 CallbackInfo info = new CallbackInfo();
1425 info.packageNames = packageNames;
1426 info.replacing = replacing;
1427 info.user = user;
1428 obtainMessage(MSG_AVAILABLE, info).sendToTarget();
1429 }
1430
1431 public void postOnPackagesUnavailable(String[] packageNames, UserHandle user,
1432 boolean replacing) {
1433 CallbackInfo info = new CallbackInfo();
1434 info.packageNames = packageNames;
1435 info.replacing = replacing;
1436 info.user = user;
1437 obtainMessage(MSG_UNAVAILABLE, info).sendToTarget();
1438 }
Kenny Guy77242752016-01-15 13:29:06 +00001439
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001440 public void postOnPackagesSuspended(String[] packageNames, Bundle launcherExtras,
1441 UserHandle user) {
Kenny Guy77242752016-01-15 13:29:06 +00001442 CallbackInfo info = new CallbackInfo();
1443 info.packageNames = packageNames;
1444 info.user = user;
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001445 info.launcherExtras = launcherExtras;
Kenny Guy77242752016-01-15 13:29:06 +00001446 obtainMessage(MSG_SUSPENDED, info).sendToTarget();
1447 }
1448
1449 public void postOnPackagesUnsuspended(String[] packageNames, UserHandle user) {
1450 CallbackInfo info = new CallbackInfo();
1451 info.packageNames = packageNames;
1452 info.user = user;
1453 obtainMessage(MSG_UNSUSPENDED, info).sendToTarget();
1454 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001455
1456 public void postOnShortcutChanged(String packageName, UserHandle user,
1457 List<ShortcutInfo> shortcuts) {
1458 CallbackInfo info = new CallbackInfo();
1459 info.packageName = packageName;
1460 info.user = user;
1461 info.shortcuts = shortcuts;
1462 obtainMessage(MSG_SHORTCUT_CHANGED, info).sendToTarget();
1463 }
Kenny Guyb42c89b2014-07-28 19:20:07 +01001464 }
Makoto Onuki2d895c32016-12-02 15:48:40 -08001465
1466 /**
Jon Miranda2b340a22019-01-25 14:03:49 -08001467 * Register a callback to watch for session lifecycle events in this user and managed profiles.
1468 * @param callback The callback to register.
1469 * @param executor {@link Executor} to handle the callbacks, cannot be null.
1470 *
1471 * @see PackageInstaller#registerSessionCallback(SessionCallback)
1472 */
1473 public void registerPackageInstallerSessionCallback(
1474 @NonNull @CallbackExecutor Executor executor, @NonNull SessionCallback callback) {
1475 if (executor == null) {
1476 throw new NullPointerException("Executor must not be null");
1477 }
1478
1479 synchronized (mDelegates) {
1480 final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
1481 executor);
1482 try {
1483 mService.registerPackageInstallerCallback(mContext.getPackageName(),
1484 delegate);
1485 } catch (RemoteException e) {
1486 throw e.rethrowFromSystemServer();
1487 }
1488 mDelegates.add(delegate);
1489 }
1490 }
1491
1492 /**
1493 * Unregisters a callback that was previously registered.
1494 *
1495 * @param callback The callback to unregister.
1496 * @see #registerPackageInstallerSessionCallback(Executor, SessionCallback)
1497 */
Jon Miranda93505982019-03-08 09:33:42 -08001498 public void unregisterPackageInstallerSessionCallback(@NonNull SessionCallback callback) {
Jon Miranda2b340a22019-01-25 14:03:49 -08001499 synchronized (mDelegates) {
1500 for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
1501 final SessionCallbackDelegate delegate = i.next();
1502 if (delegate.mCallback == callback) {
1503 mPm.getPackageInstaller().unregisterSessionCallback(delegate.mCallback);
1504 i.remove();
1505 }
1506 }
1507 }
1508 }
1509
1510 /**
1511 * Return list of all known install sessions in this user and managed profiles, regardless
1512 * of the installer.
1513 *
1514 * @see PackageInstaller#getAllSessions()
1515 */
1516 public @NonNull List<SessionInfo> getAllPackageInstallerSessions() {
1517 try {
1518 return mService.getAllSessions(mContext.getPackageName()).getList();
1519 } catch (RemoteException e) {
1520 throw e.rethrowFromSystemServer();
1521 }
1522 }
1523
1524 /**
Makoto Onuki2d895c32016-12-02 15:48:40 -08001525 * A helper method to extract a {@link PinItemRequest} set to
1526 * the {@link #EXTRA_PIN_ITEM_REQUEST} extra.
1527 */
1528 public PinItemRequest getPinItemRequest(Intent intent) {
1529 return intent.getParcelableExtra(EXTRA_PIN_ITEM_REQUEST);
1530 }
1531
1532 /**
Sunny Goyal7f7372a2017-01-24 11:53:54 -08001533 * Represents a "pin shortcut" or a "pin appwidget" request made by an app, which is sent with
1534 * an {@link #ACTION_CONFIRM_PIN_SHORTCUT} or {@link #ACTION_CONFIRM_PIN_APPWIDGET} intent
1535 * respectively to the default launcher app.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001536 *
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001537 * <h3>Request of the {@link #REQUEST_TYPE_SHORTCUT} type.
Makoto Onuki0c280712017-01-19 15:14:27 -08001538 *
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001539 * <p>A {@link #REQUEST_TYPE_SHORTCUT} request represents a request to pin a
1540 * {@link ShortcutInfo}. If the launcher accepts a request, call {@link #accept()},
1541 * or {@link #accept(Bundle)} with a null or empty Bundle. No options are defined for
1542 * pin-shortcuts requests.
1543 *
1544 * <p>{@link #getShortcutInfo()} always returns a non-null {@link ShortcutInfo} for this type.
1545 *
1546 * <p>The launcher may receive a request with a {@link ShortcutInfo} that is already pinned, in
1547 * which case {@link ShortcutInfo#isPinned()} returns true. This means the user wants to create
1548 * another pinned shortcut for a shortcut that's already pinned. If the launcher accepts it,
1549 * {@link #accept()} must still be called even though the shortcut is already pinned, and
1550 * create a new pinned shortcut icon for it.
1551 *
1552 * <p>See also {@link ShortcutManager} for more details.
1553 *
1554 * <h3>Request of the {@link #REQUEST_TYPE_APPWIDGET} type.
1555 *
1556 * <p>A {@link #REQUEST_TYPE_SHORTCUT} request represents a request to pin a
1557 * an AppWidget. If the launcher accepts a request, call {@link #accept(Bundle)} with
1558 * the appwidget integer ID set to the
1559 * {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID} extra.
1560 *
1561 * <p>{@link #getAppWidgetProviderInfo(Context)} always returns a non-null
1562 * {@link AppWidgetProviderInfo} for this type.
1563 *
1564 * <p>See also {@link AppWidgetManager} for more details.
Sunny Goyal7f7372a2017-01-24 11:53:54 -08001565 *
Makoto Onuki2d895c32016-12-02 15:48:40 -08001566 * @see #EXTRA_PIN_ITEM_REQUEST
1567 * @see #getPinItemRequest(Intent)
1568 */
1569 public static final class PinItemRequest implements Parcelable {
1570
1571 /** This is a request to pin shortcut. */
1572 public static final int REQUEST_TYPE_SHORTCUT = 1;
1573
Sunny Goyal87a563e2017-01-01 19:42:45 -08001574 /** This is a request to pin app widget. */
1575 public static final int REQUEST_TYPE_APPWIDGET = 2;
1576
Makoto Onukif5663b12017-01-09 14:09:56 -08001577 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -07001578 @IntDef(prefix = { "REQUEST_TYPE_" }, value = {
1579 REQUEST_TYPE_SHORTCUT,
1580 REQUEST_TYPE_APPWIDGET
1581 })
Makoto Onuki2d895c32016-12-02 15:48:40 -08001582 @Retention(RetentionPolicy.SOURCE)
1583 public @interface RequestType {}
1584
1585 private final int mRequestType;
Makoto Onuki2d895c32016-12-02 15:48:40 -08001586 private final IPinItemRequest mInner;
1587
1588 /**
1589 * @hide
1590 */
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001591 public PinItemRequest(IPinItemRequest inner, int type) {
Sunny Goyal87a563e2017-01-01 19:42:45 -08001592 mInner = inner;
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001593 mRequestType = type;
Makoto Onuki2d895c32016-12-02 15:48:40 -08001594 }
1595
1596 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001597 * Represents the type of a request, which is one of the {@code REQUEST_TYPE_} constants.
1598 *
1599 * @return one of the {@code REQUEST_TYPE_} constants.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001600 */
1601 @RequestType
1602 public int getRequestType() {
1603 return mRequestType;
1604 }
1605
1606 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001607 * {@link ShortcutInfo} sent by the requesting app.
1608 * Always non-null for a {@link #REQUEST_TYPE_SHORTCUT} request, and always null for a
1609 * different request type.
1610 *
1611 * @return requested {@link ShortcutInfo} when a request is of the
1612 * {@link #REQUEST_TYPE_SHORTCUT} type. Null otherwise.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001613 */
1614 @Nullable
1615 public ShortcutInfo getShortcutInfo() {
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001616 try {
1617 return mInner.getShortcutInfo();
1618 } catch (RemoteException e) {
1619 throw e.rethrowAsRuntimeException();
1620 }
Makoto Onuki2d895c32016-12-02 15:48:40 -08001621 }
1622
1623 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001624 * {@link AppWidgetProviderInfo} sent by the requesting app.
1625 * Always non-null for a {@link #REQUEST_TYPE_APPWIDGET} request, and always null for a
1626 * different request type.
1627 *
Sunny Goyale7712ad2018-03-08 11:23:06 -08001628 * <p>Launcher should not show any configuration activity associated with the provider, and
1629 * assume that the widget is already fully configured. Upon accepting the widget, it should
1630 * pass the widgetId in {@link #accept(Bundle)}.
1631 *
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001632 * @return requested {@link AppWidgetProviderInfo} when a request is of the
1633 * {@link #REQUEST_TYPE_APPWIDGET} type. Null otherwise.
Sunny Goyal87a563e2017-01-01 19:42:45 -08001634 */
1635 @Nullable
Sunny Goyal970d4b42017-01-19 15:07:36 -08001636 public AppWidgetProviderInfo getAppWidgetProviderInfo(Context context) {
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001637 try {
1638 final AppWidgetProviderInfo info = mInner.getAppWidgetProviderInfo();
1639 if (info == null) {
1640 return null;
1641 }
Sunny Goyal970d4b42017-01-19 15:07:36 -08001642 info.updateDimensions(context.getResources().getDisplayMetrics());
1643 return info;
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001644 } catch (RemoteException e) {
1645 throw e.rethrowAsRuntimeException();
Sunny Goyal970d4b42017-01-19 15:07:36 -08001646 }
Sunny Goyal87a563e2017-01-01 19:42:45 -08001647 }
1648
1649 /**
Sunny Goyal4ad6b572017-02-28 11:11:51 -08001650 * Any extras sent by the requesting app.
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001651 *
1652 * @return For a shortcut request, this method always return null. For an AppWidget
1653 * request, this method returns the extras passed to the
1654 * {@link android.appwidget.AppWidgetManager#requestPinAppWidget(
1655 * ComponentName, Bundle, PendingIntent)} API. See {@link AppWidgetManager} for details.
Sunny Goyal4ad6b572017-02-28 11:11:51 -08001656 */
1657 @Nullable
1658 public Bundle getExtras() {
1659 try {
1660 return mInner.getExtras();
1661 } catch (RemoteException e) {
1662 throw e.rethrowAsRuntimeException();
1663 }
1664 }
1665
1666 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001667 * Return whether a request is still valid.
1668 *
1669 * @return {@code TRUE} if a request is valid and {@link #accept(Bundle)} may be called.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001670 */
1671 public boolean isValid() {
1672 try {
1673 return mInner.isValid();
1674 } catch (RemoteException e) {
1675 return false;
1676 }
1677 }
1678
1679 /**
1680 * Called by the receiving launcher app when the user accepts the request.
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001681 *
1682 * @param options must be set for a {@link #REQUEST_TYPE_APPWIDGET} request.
1683 *
1684 * @return {@code TRUE} if the shortcut or the AppWidget has actually been pinned.
1685 * {@code FALSE} if the item hasn't been pinned, for example, because the request had
1686 * already been canceled, in which case the launcher must not pin the requested item.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001687 */
1688 public boolean accept(@Nullable Bundle options) {
1689 try {
1690 return mInner.accept(options);
1691 } catch (RemoteException e) {
1692 throw e.rethrowFromSystemServer();
1693 }
1694 }
1695
1696 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001697 * Called by the receiving launcher app when the user accepts the request, with no options.
1698 *
1699 * @return {@code TRUE} if the shortcut or the AppWidget has actually been pinned.
1700 * {@code FALSE} if the item hasn't been pinned, for example, because the request had
1701 * already been canceled, in which case the launcher must not pin the requested item.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001702 */
1703 public boolean accept() {
1704 return accept(/* options= */ null);
1705 }
1706
1707 private PinItemRequest(Parcel source) {
1708 final ClassLoader cl = getClass().getClassLoader();
1709
1710 mRequestType = source.readInt();
Makoto Onuki2d895c32016-12-02 15:48:40 -08001711 mInner = IPinItemRequest.Stub.asInterface(source.readStrongBinder());
1712 }
1713
1714 @Override
1715 public void writeToParcel(Parcel dest, int flags) {
1716 dest.writeInt(mRequestType);
Makoto Onuki2d895c32016-12-02 15:48:40 -08001717 dest.writeStrongBinder(mInner.asBinder());
1718 }
1719
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001720 public static final @android.annotation.NonNull Creator<PinItemRequest> CREATOR =
Makoto Onuki2d895c32016-12-02 15:48:40 -08001721 new Creator<PinItemRequest>() {
1722 public PinItemRequest createFromParcel(Parcel source) {
1723 return new PinItemRequest(source);
1724 }
1725 public PinItemRequest[] newArray(int size) {
1726 return new PinItemRequest[size];
1727 }
1728 };
1729
1730 @Override
1731 public int describeContents() {
1732 return 0;
1733 }
1734 }
Varun Shah2546cef2019-01-11 15:50:54 -08001735
1736 /**
1737 * A class that encapsulates information about the usage limit set for an app or
1738 * a group of apps.
1739 *
Varun Shah9c6f72b2019-01-25 21:13:56 -08001740 * <p>The launcher can query specifics about the usage limit such as how much usage time
1741 * the limit has and how much of the total usage time is remaining via the APIs available
1742 * in this class.
Varun Shah2546cef2019-01-11 15:50:54 -08001743 *
1744 * @see #getAppUsageLimit(String, UserHandle)
Sunny Goyalbeee1972019-03-29 11:38:16 -07001745 * @hide
Varun Shah2546cef2019-01-11 15:50:54 -08001746 */
Sunny Goyalbeee1972019-03-29 11:38:16 -07001747 @SystemApi
Varun Shah2546cef2019-01-11 15:50:54 -08001748 public static final class AppUsageLimit implements Parcelable {
Varun Shah2546cef2019-01-11 15:50:54 -08001749 private final long mTotalUsageLimit;
1750 private final long mUsageRemaining;
1751
1752 /** @hide */
Varun Shah9c6f72b2019-01-25 21:13:56 -08001753 public AppUsageLimit(long totalUsageLimit, long usageRemaining) {
Varun Shah2546cef2019-01-11 15:50:54 -08001754 this.mTotalUsageLimit = totalUsageLimit;
1755 this.mUsageRemaining = usageRemaining;
1756 }
1757
1758 /**
Varun Shah2546cef2019-01-11 15:50:54 -08001759 * Returns the total usage limit in milliseconds set for an app or a group of apps.
1760 *
1761 * @return the total usage limit in milliseconds
1762 */
1763 public long getTotalUsageLimit() {
1764 return mTotalUsageLimit;
1765 }
1766
1767 /**
1768 * Returns the usage remaining in milliseconds for an app or the group of apps
1769 * this limit refers to.
1770 *
1771 * @return the usage remaining in milliseconds
1772 */
1773 public long getUsageRemaining() {
1774 return mUsageRemaining;
1775 }
1776
1777 private AppUsageLimit(Parcel source) {
Varun Shah2546cef2019-01-11 15:50:54 -08001778 mTotalUsageLimit = source.readLong();
1779 mUsageRemaining = source.readLong();
1780 }
1781
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001782 public static final @android.annotation.NonNull Creator<AppUsageLimit> CREATOR = new Creator<AppUsageLimit>() {
Varun Shah2546cef2019-01-11 15:50:54 -08001783 @Override
1784 public AppUsageLimit createFromParcel(Parcel source) {
1785 return new AppUsageLimit(source);
1786 }
1787
1788 @Override
1789 public AppUsageLimit[] newArray(int size) {
1790 return new AppUsageLimit[size];
1791 }
1792 };
1793
1794 @Override
1795 public int describeContents() {
1796 return 0;
1797 }
1798
1799 @Override
1800 public void writeToParcel(Parcel dest, int flags) {
Varun Shah2546cef2019-01-11 15:50:54 -08001801 dest.writeLong(mTotalUsageLimit);
1802 dest.writeLong(mUsageRemaining);
1803 }
1804 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001805}