blob: bf556ba0b6685c7ef41f5ebce1cacc916a8a1e31 [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;
Makoto Onukib1588c02017-10-12 15:11:45 -070025import android.annotation.SystemService;
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070026import android.annotation.TestApi;
Mathew Inwood5c0d3542018-08-14 13:54:31 +010027import android.annotation.UnsupportedAppUsage;
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;
Makoto Onuki83f6d2d2016-07-11 14:30:19 -070031import android.content.ActivityNotFoundException;
Amith Yamasani4f582632014-02-19 14:31:52 -080032import android.content.ComponentName;
33import android.content.Context;
34import android.content.Intent;
Sunny Goyala6be88a2017-01-12 16:27:58 -080035import android.content.IntentSender;
Jon Miranda2b340a22019-01-25 14:03:49 -080036import android.content.pm.PackageInstaller.SessionCallback;
37import android.content.pm.PackageInstaller.SessionCallbackDelegate;
38import android.content.pm.PackageInstaller.SessionInfo;
Kenny Guy77242752016-01-15 13:29:06 +000039import android.content.pm.PackageManager.ApplicationInfoFlags;
Makoto Onuki04b9aab2016-05-23 17:13:30 -070040import android.content.pm.PackageManager.NameNotFoundException;
41import android.content.res.Resources;
42import android.graphics.Bitmap;
43import android.graphics.BitmapFactory;
Amith Yamasani4f582632014-02-19 14:31:52 -080044import android.graphics.Rect;
Makoto Onukib1588c02017-10-12 15:11:45 -070045import android.graphics.drawable.AdaptiveIconDrawable;
Makoto Onuki04b9aab2016-05-23 17:13:30 -070046import android.graphics.drawable.BitmapDrawable;
Makoto Onuki20c95f82016-05-11 16:51:01 -070047import android.graphics.drawable.Drawable;
Makoto Onuki2d895c32016-12-02 15:48:40 -080048import android.graphics.drawable.Icon;
Mathew Inwood8c854f82018-09-14 12:35:36 +010049import android.os.Build;
Amith Yamasani4f582632014-02-19 14:31:52 -080050import android.os.Bundle;
Kenny Guyb42c89b2014-07-28 19:20:07 +010051import android.os.Handler;
52import android.os.Looper;
53import android.os.Message;
Makoto Onuki2d895c32016-12-02 15:48:40 -080054import android.os.Parcel;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080055import android.os.ParcelFileDescriptor;
Makoto Onuki2d895c32016-12-02 15:48:40 -080056import android.os.Parcelable;
Amith Yamasani4f582632014-02-19 14:31:52 -080057import android.os.RemoteException;
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -070058import android.os.ServiceManager;
Amith Yamasani4f582632014-02-19 14:31:52 -080059import android.os.UserHandle;
Amith Yamasanie781c812014-05-28 15:28:18 -070060import android.os.UserManager;
Makoto Onuki04b9aab2016-05-23 17:13:30 -070061import android.util.DisplayMetrics;
Amith Yamasani4f582632014-02-19 14:31:52 -080062import android.util.Log;
63
Makoto Onuki7c7fbf62017-04-14 11:03:56 -070064import com.android.internal.util.Preconditions;
65
Makoto Onuki04b9aab2016-05-23 17:13:30 -070066import java.io.IOException;
Makoto Onuki6f7362d92016-03-04 13:39:41 -080067import java.lang.annotation.Retention;
68import java.lang.annotation.RetentionPolicy;
Amith Yamasani4f582632014-02-19 14:31:52 -080069import java.util.ArrayList;
Makoto Onukib6d35232016-04-04 15:57:17 -070070import java.util.Arrays;
Amith Yamasani4f582632014-02-19 14:31:52 -080071import java.util.Collections;
Jon Miranda2b340a22019-01-25 14:03:49 -080072import java.util.Iterator;
Amith Yamasani4f582632014-02-19 14:31:52 -080073import java.util.List;
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
Ricky Waie346a492019-01-21 14:54:32 +0000145 /**
146 * Metadata key that specifies vouched certs, so any apps signed by a cert in vouched certs
147 * will not show hidden icon in launcher even it does not have a launcher visible activity.
148 *
149 * If an app has this metadata in manifest, it won't be eligible to hide its icon even if its
150 * cert is in vouched certs list.
151 *
152 * @hide
153 */
154 public static final String VOUCHED_CERTS_KEY = "vouched_certs";
155
Makoto Onukide3c16c2017-01-26 11:39:31 -0800156 private final Context mContext;
Mathew Inwood8c854f82018-09-14 12:35:36 +0100157 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Makoto Onukide3c16c2017-01-26 11:39:31 -0800158 private final ILauncherApps mService;
Mathew Inwood5c0d3542018-08-14 13:54:31 +0100159 @UnsupportedAppUsage
Makoto Onukide3c16c2017-01-26 11:39:31 -0800160 private final PackageManager mPm;
161 private final UserManager mUserManager;
Amith Yamasani4f582632014-02-19 14:31:52 -0800162
Jon Miranda2b340a22019-01-25 14:03:49 -0800163 private final List<CallbackMessageHandler> mCallbacks = new ArrayList<>();
164 private final List<SessionCallbackDelegate> mDelegates = new ArrayList<>();
Kenny Guyc01545372014-06-16 14:17:26 +0100165
166 /**
167 * Callbacks for package changes to this and related managed profiles.
168 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100169 public static abstract class Callback {
Kenny Guyc01545372014-06-16 14:17:26 +0100170 /**
171 * Indicates that a package was removed from the specified profile.
172 *
Kenny Guyb42c89b2014-07-28 19:20:07 +0100173 * If a package is removed while being updated onPackageChanged will be
174 * called instead.
175 *
Kenny Guyc01545372014-06-16 14:17:26 +0100176 * @param packageName The name of the package that was removed.
177 * @param user The UserHandle of the profile that generated the change.
178 */
179 abstract public void onPackageRemoved(String packageName, UserHandle user);
180
181 /**
182 * Indicates that a package was added to the specified profile.
183 *
Kenny Guyb42c89b2014-07-28 19:20:07 +0100184 * If a package is added while being updated then onPackageChanged will be
185 * called instead.
186 *
Kenny Guyc01545372014-06-16 14:17:26 +0100187 * @param packageName The name of the package that was added.
188 * @param user The UserHandle of the profile that generated the change.
189 */
190 abstract public void onPackageAdded(String packageName, UserHandle user);
191
192 /**
193 * Indicates that a package was modified in the specified profile.
Kenny Guyb42c89b2014-07-28 19:20:07 +0100194 * This can happen, for example, when the package is updated or when
195 * one or more components are enabled or disabled.
Kenny Guyc01545372014-06-16 14:17:26 +0100196 *
197 * @param packageName The name of the package that has changed.
198 * @param user The UserHandle of the profile that generated the change.
199 */
200 abstract public void onPackageChanged(String packageName, UserHandle user);
201
202 /**
203 * Indicates that one or more packages have become available. For
204 * example, this can happen when a removable storage card has
205 * reappeared.
206 *
207 * @param packageNames The names of the packages that have become
208 * available.
209 * @param user The UserHandle of the profile that generated the change.
210 * @param replacing Indicates whether these packages are replacing
211 * existing ones.
212 */
213 abstract public void onPackagesAvailable(String[] packageNames, UserHandle user,
214 boolean replacing);
215
216 /**
217 * Indicates that one or more packages have become unavailable. For
218 * example, this can happen when a removable storage card has been
219 * removed.
220 *
221 * @param packageNames The names of the packages that have become
222 * unavailable.
223 * @param user The UserHandle of the profile that generated the change.
224 * @param replacing Indicates whether the packages are about to be
225 * replaced with new versions.
226 */
227 abstract public void onPackagesUnavailable(String[] packageNames, UserHandle user,
228 boolean replacing);
Kenny Guy77242752016-01-15 13:29:06 +0000229
230 /**
231 * Indicates that one or more packages have been suspended. For
232 * example, this can happen when a Device Administrator suspends
233 * an applicaton.
234 *
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700235 * <p>Note: On devices running {@link android.os.Build.VERSION_CODES#P Android P} or higher,
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700236 * any apps that override {@link #onPackagesSuspended(String[], UserHandle, Bundle)} will
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700237 * not receive this callback.
238 *
Kenny Guy77242752016-01-15 13:29:06 +0000239 * @param packageNames The names of the packages that have just been
240 * suspended.
241 * @param user The UserHandle of the profile that generated the change.
242 */
243 public void onPackagesSuspended(String[] packageNames, UserHandle user) {
244 }
245
246 /**
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700247 * Indicates that one or more packages have been suspended. A device administrator or an app
248 * with {@code android.permission.SUSPEND_APPS} can do this.
249 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700250 * <p>A suspending app with the permission {@code android.permission.SUSPEND_APPS} can
251 * optionally provide a {@link Bundle} of extra information that it deems helpful for the
252 * launcher to handle the suspended state of these packages. The contents of this
Suprabh Shukla3e03ab92018-04-11 16:03:49 -0700253 * {@link Bundle} are supposed to be a contract between the suspending app and the launcher.
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700254 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700255 * @param packageNames The names of the packages that have just been suspended.
256 * @param user the user for which the given packages were suspended.
257 * @param launcherExtras A {@link Bundle} of extras for the launcher, if provided to the
258 * system, {@code null} otherwise.
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700259 * @see PackageManager#isPackageSuspended()
260 * @see #getSuspendedPackageLauncherExtras(String, UserHandle)
261 */
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700262 public void onPackagesSuspended(String[] packageNames, UserHandle user,
263 @Nullable Bundle launcherExtras) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700264 onPackagesSuspended(packageNames, user);
265 }
266
267 /**
Kenny Guy77242752016-01-15 13:29:06 +0000268 * Indicates that one or more packages have been unsuspended. For
269 * example, this can happen when a Device Administrator unsuspends
270 * an applicaton.
271 *
272 * @param packageNames The names of the packages that have just been
273 * unsuspended.
274 * @param user The UserHandle of the profile that generated the change.
275 */
276 public void onPackagesUnsuspended(String[] packageNames, UserHandle user) {
277 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800278
279 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700280 * Indicates that one or more shortcuts of any kind (dynamic, pinned, or manifest)
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800281 * have been added, updated or removed.
282 *
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800283 * <p>Only the applications that are allowed to access the shortcut information,
284 * as defined in {@link #hasShortcutHostPermission()}, will receive it.
285 *
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800286 * @param packageName The name of the package that has the shortcuts.
Makoto Onukife9c9662016-07-25 15:12:23 -0700287 * @param shortcuts All shortcuts from the package (dynamic, manifest and/or pinned).
288 * Only "key" information will be provided, as defined in
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700289 * {@link ShortcutInfo#hasKeyFieldsOnly()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800290 * @param user The UserHandle of the profile that generated the change.
Makoto Onuki4a910962016-07-07 13:57:34 -0700291 *
292 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800293 */
294 public void onShortcutsChanged(@NonNull String packageName,
295 @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
296 }
297 }
298
299 /**
300 * Represents a query passed to {@link #getShortcuts(ShortcutQuery, UserHandle)}.
301 */
302 public static class ShortcutQuery {
303 /**
304 * Include dynamic shortcuts in the result.
305 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700306 public static final int FLAG_MATCH_DYNAMIC = 1 << 0;
307
308 /** @hide kept for unit tests */
309 @Deprecated
310 public static final int FLAG_GET_DYNAMIC = FLAG_MATCH_DYNAMIC;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800311
312 /**
313 * Include pinned shortcuts in the result.
Makoto Onuki88b4dcc2017-12-07 15:53:56 -0800314 *
315 * <p>If you are the selected assistant app, and wishes to fetch all shortcuts that the
316 * user owns on the launcher (or by other launchers, in case the user has multiple), use
317 * {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} instead.
318 *
319 * <p>If you're a regular launcher app, there's no way to get shortcuts pinned by other
320 * launchers, and {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} will be ignored. So use this
321 * flag to get own pinned shortcuts.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800322 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700323 public static final int FLAG_MATCH_PINNED = 1 << 1;
324
325 /** @hide kept for unit tests */
326 @Deprecated
327 public static final int FLAG_GET_PINNED = FLAG_MATCH_PINNED;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800328
329 /**
Makoto Onuki22fcc682016-05-17 14:52:19 -0700330 * Include manifest shortcuts in the result.
331 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700332 public static final int FLAG_MATCH_MANIFEST = 1 << 3;
333
334 /** @hide kept for unit tests */
335 @Deprecated
336 public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700337
Hakan Seyalioglu58fc95d2016-12-13 15:23:22 -0800338 /**
Makoto Onuki35559d62017-11-06 16:26:32 -0800339 * Include all pinned shortcuts by any launchers, not just by the caller,
Makoto Onuki634cecb2017-10-13 17:10:48 -0700340 * in the result.
Makoto Onuki35559d62017-11-06 16:26:32 -0800341 *
Makoto Onuki88b4dcc2017-12-07 15:53:56 -0800342 * <p>The caller must be the selected assistant app to use this flag, or have the system
Makoto Onuki35559d62017-11-06 16:26:32 -0800343 * {@code ACCESS_SHORTCUTS} permission.
Makoto Onuki88b4dcc2017-12-07 15:53:56 -0800344 *
345 * <p>If you are the selected assistant app, and wishes to fetch all shortcuts that the
346 * user owns on the launcher (or by other launchers, in case the user has multiple), use
347 * {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} instead.
348 *
349 * <p>If you're a regular launcher app (or any app that's not the selected assistant app)
350 * then this flag will be ignored.
Makoto Onuki634cecb2017-10-13 17:10:48 -0700351 */
Makoto Onuki35559d62017-11-06 16:26:32 -0800352 public static final int FLAG_MATCH_PINNED_BY_ANY_LAUNCHER = 1 << 10;
Makoto Onuki634cecb2017-10-13 17:10:48 -0700353
354 /**
355 * FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST
Hakan Seyalioglu58fc95d2016-12-13 15:23:22 -0800356 * @hide
357 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700358 public static final int FLAG_MATCH_ALL_KINDS =
Makoto Onuki634cecb2017-10-13 17:10:48 -0700359 FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST;
360
361 /**
362 * FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST | FLAG_MATCH_ALL_PINNED
363 * @hide
364 */
365 public static final int FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED =
Makoto Onuki35559d62017-11-06 16:26:32 -0800366 FLAG_MATCH_ALL_KINDS | FLAG_MATCH_PINNED_BY_ANY_LAUNCHER;
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700367
Makoto Onukib5a012f2016-06-21 11:13:53 -0700368 /** @hide kept for unit tests */
369 @Deprecated
370 public static final int FLAG_GET_ALL_KINDS = FLAG_MATCH_ALL_KINDS;
371
Makoto Onuki22fcc682016-05-17 14:52:19 -0700372 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700373 * Requests "key" fields only. See {@link ShortcutInfo#hasKeyFieldsOnly()}'s javadoc to
374 * see which fields fields "key".
375 * This allows quicker access to shortcut information in order to
376 * determine whether the caller's in-memory cache needs to be updated.
Makoto Onuki4a910962016-07-07 13:57:34 -0700377 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700378 * <p>Typically, launcher applications cache all or most shortcut information
379 * in memory in order to show shortcuts without a delay.
380 *
381 * When a given launcher application wants to update its cache, such as when its process
382 * restarts, it can fetch shortcut information with this flag.
383 * The application can then check {@link ShortcutInfo#getLastChangedTimestamp()} for each
384 * shortcut, fetching a shortcut's non-key information only if that shortcut has been
385 * updated.
Makoto Onuki4a910962016-07-07 13:57:34 -0700386 *
387 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800388 */
389 public static final int FLAG_GET_KEY_FIELDS_ONLY = 1 << 2;
390
391 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700392 @IntDef(flag = true, prefix = { "FLAG_" }, value = {
393 FLAG_MATCH_DYNAMIC,
394 FLAG_MATCH_PINNED,
395 FLAG_MATCH_MANIFEST,
396 FLAG_GET_KEY_FIELDS_ONLY,
397 FLAG_MATCH_MANIFEST,
398 })
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800399 @Retention(RetentionPolicy.SOURCE)
400 public @interface QueryFlags {}
401
402 long mChangedSince;
403
404 @Nullable
405 String mPackage;
406
407 @Nullable
Makoto Onukiabe84422016-04-07 09:41:19 -0700408 List<String> mShortcutIds;
409
410 @Nullable
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800411 ComponentName mActivity;
412
413 @QueryFlags
414 int mQueryFlags;
415
416 public ShortcutQuery() {
417 }
418
419 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700420 * If non-zero, returns only shortcuts that have been added or updated
421 * since the given timestamp, expressed in milliseconds since the Epoch&mdash;see
422 * {@link System#currentTimeMillis()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800423 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700424 public ShortcutQuery setChangedSince(long changedSince) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800425 mChangedSince = changedSince;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700426 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800427 }
428
429 /**
430 * If non-null, returns only shortcuts from the package.
431 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700432 public ShortcutQuery setPackage(@Nullable String packageName) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800433 mPackage = packageName;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700434 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800435 }
436
437 /**
Makoto Onukiabe84422016-04-07 09:41:19 -0700438 * If non-null, return only the specified shortcuts by ID. When setting this field,
Makoto Onuki4a910962016-07-07 13:57:34 -0700439 * a package name must also be set with {@link #setPackage}.
Makoto Onukiabe84422016-04-07 09:41:19 -0700440 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700441 public ShortcutQuery setShortcutIds(@Nullable List<String> shortcutIds) {
Makoto Onukiabe84422016-04-07 09:41:19 -0700442 mShortcutIds = shortcutIds;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700443 return this;
Makoto Onukiabe84422016-04-07 09:41:19 -0700444 }
445
446 /**
Makoto Onuki22fcc682016-05-17 14:52:19 -0700447 * If non-null, returns only shortcuts associated with the activity; i.e.
448 * {@link ShortcutInfo}s whose {@link ShortcutInfo#getActivity()} are equal
449 * to {@code activity}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800450 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700451 public ShortcutQuery setActivity(@Nullable ComponentName activity) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800452 mActivity = activity;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700453 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800454 }
455
Hakan Seyalioglu58fc95d2016-12-13 15:23:22 -0800456 /**
Makoto Onukife9c9662016-07-25 15:12:23 -0700457 * Set query options. At least one of the {@code MATCH} flags should be set. Otherwise,
458 * no shortcuts will be returned.
Makoto Onuki4a910962016-07-07 13:57:34 -0700459 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700460 * <ul>
461 * <li>{@link #FLAG_MATCH_DYNAMIC}
462 * <li>{@link #FLAG_MATCH_PINNED}
463 * <li>{@link #FLAG_MATCH_MANIFEST}
464 * <li>{@link #FLAG_GET_KEY_FIELDS_ONLY}
465 * </ul>
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800466 */
Makoto Onuki22fcc682016-05-17 14:52:19 -0700467 public ShortcutQuery setQueryFlags(@QueryFlags int queryFlags) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800468 mQueryFlags = queryFlags;
Makoto Onuki22fcc682016-05-17 14:52:19 -0700469 return this;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800470 }
Kenny Guyc01545372014-06-16 14:17:26 +0100471 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800472
Amith Yamasani4f582632014-02-19 14:31:52 -0800473 /** @hide */
474 public LauncherApps(Context context, ILauncherApps service) {
475 mContext = context;
476 mService = service;
Amith Yamasanie781c812014-05-28 15:28:18 -0700477 mPm = context.getPackageManager();
Makoto Onukide3c16c2017-01-26 11:39:31 -0800478 mUserManager = context.getSystemService(UserManager.class);
Amith Yamasani4f582632014-02-19 14:31:52 -0800479 }
480
Makoto Onuki5ba0d3e2016-04-11 14:03:46 -0700481 /** @hide */
482 @TestApi
483 public LauncherApps(Context context) {
484 this(context, ILauncherApps.Stub.asInterface(
485 ServiceManager.getService(Context.LAUNCHER_APPS_SERVICE)));
486 }
487
Amith Yamasani4f582632014-02-19 14:31:52 -0800488 /**
Makoto Onukide3c16c2017-01-26 11:39:31 -0800489 * Show an error log on logcat, when the calling user is a managed profile, and the target
490 * user is different from the calling user, in order to help developers to detect it.
491 */
492 private void logErrorForInvalidProfileAccess(@NonNull UserHandle target) {
493 if (UserHandle.myUserId() != target.getIdentifier() && mUserManager.isManagedProfile()) {
Makoto Onuki3cc7cd12017-04-03 12:48:42 -0700494 Log.w(TAG, "Accessing other profiles/users from managed profile is no longer allowed.");
Makoto Onukide3c16c2017-01-26 11:39:31 -0800495 }
496 }
497
498 /**
Makoto Onukiaecbd032017-01-19 12:11:11 -0800499 * Return a list of profiles that the caller can access via the {@link LauncherApps} APIs.
500 *
501 * <p>If the caller is running on a managed profile, it'll return only the current profile.
502 * Otherwise it'll return the same list as {@link UserManager#getUserProfiles()} would.
503 */
504 public List<UserHandle> getProfiles() {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800505 if (mUserManager.isManagedProfile()) {
Makoto Onukiaecbd032017-01-19 12:11:11 -0800506 // If it's a managed profile, only return the current profile.
507 final List result = new ArrayList(1);
508 result.add(android.os.Process.myUserHandle());
509 return result;
510 } else {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800511 return mUserManager.getUserProfiles();
Makoto Onukiaecbd032017-01-19 12:11:11 -0800512 }
513 }
514
515 /**
Amith Yamasani4f582632014-02-19 14:31:52 -0800516 * Retrieves a list of launchable activities that match {@link Intent#ACTION_MAIN} and
Ricky Wai905908f2019-01-29 15:19:52 +0000517 * {@link Intent#CATEGORY_LAUNCHER}, for a specified user. Result may include
518 * synthesized activities like app details Activity injected by system.
Amith Yamasani4f582632014-02-19 14:31:52 -0800519 *
520 * @param packageName The specific package to query. If null, it checks all installed packages
521 * in the profile.
522 * @param user The UserHandle of the profile.
523 * @return List of launchable activities. Can be an empty list but will not be null.
524 */
525 public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800526 logErrorForInvalidProfileAccess(user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800527 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800528 return convertToActivityList(mService.getLauncherActivities(mContext.getPackageName(),
529 packageName, user), user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800530 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700531 throw re.rethrowFromSystemServer();
Amith Yamasani4f582632014-02-19 14:31:52 -0800532 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800533 }
534
Amith Yamasani4f582632014-02-19 14:31:52 -0800535 /**
536 * Returns the activity info for a given intent and user handle, if it resolves. Otherwise it
537 * returns null.
538 *
539 * @param intent The intent to find a match for.
540 * @param user The profile to look in for a match.
541 * @return An activity info object if there is a match.
542 */
543 public LauncherActivityInfo resolveActivity(Intent intent, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800544 logErrorForInvalidProfileAccess(user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800545 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800546 ActivityInfo ai = mService.resolveActivity(mContext.getPackageName(),
547 intent.getComponent(), user);
Sunny Goyal45d3e972016-03-31 12:38:17 -0700548 if (ai != null) {
549 LauncherActivityInfo info = new LauncherActivityInfo(mContext, ai, user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800550 return info;
551 }
552 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700553 throw re.rethrowFromSystemServer();
Amith Yamasani4f582632014-02-19 14:31:52 -0800554 }
555 return null;
556 }
557
558 /**
Kenny Guyf939dba2014-08-15 15:32:34 +0100559 * Starts a Main activity in the specified profile.
Amith Yamasani4f582632014-02-19 14:31:52 -0800560 *
561 * @param component The ComponentName of the activity to launch
Amith Yamasanie781c812014-05-28 15:28:18 -0700562 * @param user The UserHandle of the profile
563 * @param sourceBounds The Rect containing the source bounds of the clicked icon
564 * @param opts Options to pass to startActivity
565 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100566 public void startMainActivity(ComponentName component, UserHandle user, Rect sourceBounds,
Amith Yamasanie781c812014-05-28 15:28:18 -0700567 Bundle opts) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800568 logErrorForInvalidProfileAccess(user);
Amith Yamasani5abdbb62014-04-08 17:23:46 -0700569 if (DEBUG) {
Kenny Guyf939dba2014-08-15 15:32:34 +0100570 Log.i(TAG, "StartMainActivity " + component + " " + user.getIdentifier());
Amith Yamasani5abdbb62014-04-08 17:23:46 -0700571 }
Amith Yamasani4f582632014-02-19 14:31:52 -0800572 try {
Makoto Onuki1a342742018-04-26 14:56:59 -0700573 mService.startActivityAsUser(mContext.getIApplicationThread(),
574 mContext.getPackageName(),
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800575 component, sourceBounds, opts, user);
Amith Yamasani4f582632014-02-19 14:31:52 -0800576 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700577 throw re.rethrowFromSystemServer();
Amith Yamasani4f582632014-02-19 14:31:52 -0800578 }
579 }
580
581 /**
Jon Miranda2b340a22019-01-25 14:03:49 -0800582 * Starts an activity to show the details of the specified session.
583 *
584 * @param sessionInfo The SessionInfo of the session
585 * @param sourceBounds The Rect containing the source bounds of the clicked icon
586 * @param opts Options to pass to startActivity
587 */
588 public void startPackageInstallerSessionDetailsActivity(SessionInfo sessionInfo,
589 Rect sourceBounds, Bundle opts) {
590 try {
591 mService.startSessionDetailsActivityAsUser(mContext.getIApplicationThread(),
592 mContext.getPackageName(), sessionInfo, sourceBounds, opts,
593 sessionInfo.getUser());
594 } catch (RemoteException re) {
595 throw re.rethrowFromSystemServer();
596 }
597 }
598
599 /**
Kenny Guy466d2032014-07-23 12:23:35 +0100600 * Starts the settings activity to show the application details for a
601 * package in the specified profile.
602 *
603 * @param component The ComponentName of the package to launch settings for.
604 * @param user The UserHandle of the profile
605 * @param sourceBounds The Rect containing the source bounds of the clicked icon
606 * @param opts Options to pass to startActivity
607 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100608 public void startAppDetailsActivity(ComponentName component, UserHandle user,
Kenny Guy466d2032014-07-23 12:23:35 +0100609 Rect sourceBounds, Bundle opts) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800610 logErrorForInvalidProfileAccess(user);
Kenny Guy466d2032014-07-23 12:23:35 +0100611 try {
Makoto Onuki1a342742018-04-26 14:56:59 -0700612 mService.showAppDetailsAsUser(mContext.getIApplicationThread(),
613 mContext.getPackageName(),
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800614 component, sourceBounds, opts, user);
Kenny Guy466d2032014-07-23 12:23:35 +0100615 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700616 throw re.rethrowFromSystemServer();
Kenny Guy466d2032014-07-23 12:23:35 +0100617 }
618 }
619
620 /**
Sunny Goyala6be88a2017-01-12 16:27:58 -0800621 * Retrieves a list of config activities for creating {@link ShortcutInfo}.
622 *
623 * @param packageName The specific package to query. If null, it checks all installed packages
624 * in the profile.
625 * @param user The UserHandle of the profile.
626 * @return List of config activities. Can be an empty list but will not be null.
627 *
628 * @see Intent#ACTION_CREATE_SHORTCUT
629 * @see #getShortcutConfigActivityIntent(LauncherActivityInfo)
630 */
631 public List<LauncherActivityInfo> getShortcutConfigActivityList(@Nullable String packageName,
632 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800633 logErrorForInvalidProfileAccess(user);
Sunny Goyala6be88a2017-01-12 16:27:58 -0800634 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800635 return convertToActivityList(mService.getShortcutConfigActivities(
636 mContext.getPackageName(), packageName, user),
Sunny Goyala6be88a2017-01-12 16:27:58 -0800637 user);
638 } catch (RemoteException re) {
639 throw re.rethrowFromSystemServer();
640 }
641 }
642
643 private List<LauncherActivityInfo> convertToActivityList(
644 @Nullable ParceledListSlice<ResolveInfo> activities, UserHandle user) {
645 if (activities == null) {
646 return Collections.EMPTY_LIST;
647 }
648 ArrayList<LauncherActivityInfo> lais = new ArrayList<>();
649 for (ResolveInfo ri : activities.getList()) {
650 LauncherActivityInfo lai = new LauncherActivityInfo(mContext, ri.activityInfo, user);
651 if (DEBUG) {
652 Log.v(TAG, "Returning activity for profile " + user + " : "
653 + lai.getComponentName());
654 }
655 lais.add(lai);
656 }
657 return lais;
658 }
659
660 /**
661 * Returns an intent sender which can be used to start the configure activity for creating
662 * custom shortcuts. Use this method if the provider is in another profile as you are not
663 * allowed to start an activity in another profile.
664 *
665 * <p>The caller should receive {@link PinItemRequest} in onActivityResult on
666 * {@link android.app.Activity#RESULT_OK}.
667 *
668 * <p>Callers must be allowed to access the shortcut information, as defined in {@link
669 * #hasShortcutHostPermission()}.
670 *
671 * @param info a configuration activity returned by {@link #getShortcutConfigActivityList}
672 *
673 * @throws IllegalStateException when the user is locked or not running.
674 * @throws SecurityException if {@link #hasShortcutHostPermission()} is false.
675 *
676 * @see #getPinItemRequest(Intent)
677 * @see Intent#ACTION_CREATE_SHORTCUT
678 * @see android.app.Activity#startIntentSenderForResult
679 */
Makoto Onukide3c16c2017-01-26 11:39:31 -0800680 @Nullable
Sunny Goyala6be88a2017-01-12 16:27:58 -0800681 public IntentSender getShortcutConfigActivityIntent(@NonNull LauncherActivityInfo info) {
682 try {
683 return mService.getShortcutConfigActivityIntent(
684 mContext.getPackageName(), info.getComponentName(), info.getUser());
685 } catch (RemoteException re) {
686 throw re.rethrowFromSystemServer();
687 }
688 }
689
690 /**
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100691 * Checks if the package is installed and enabled for a profile.
692 *
693 * @param packageName The package to check.
694 * @param user The UserHandle of the profile.
695 *
696 * @return true if the package exists and is enabled.
697 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100698 public boolean isPackageEnabled(String packageName, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800699 logErrorForInvalidProfileAccess(user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100700 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800701 return mService.isPackageEnabled(mContext.getPackageName(), packageName, user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100702 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700703 throw re.rethrowFromSystemServer();
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100704 }
705 }
706
707 /**
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700708 * Gets the launcher extras supplied to the system when the given package was suspended via
709 * {@code PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
710 * PersistableBundle, String)}.
711 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700712 * <p>The contents of this {@link Bundle} are supposed to be a contract between the suspending
713 * app and the launcher.
714 *
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700715 * <p>Note: This just returns whatever extras were provided to the system, <em>which might
716 * even be {@code null}.</em>
717 *
718 * @param packageName The package for which to fetch the launcher extras.
719 * @param user The {@link UserHandle} of the profile.
720 * @return A {@link Bundle} of launcher extras. Or {@code null} if the package is not currently
721 * suspended.
722 *
Suprabh Shukla96212bc2018-04-10 15:04:51 -0700723 * @see Callback#onPackagesSuspended(String[], UserHandle, Bundle)
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700724 * @see PackageManager#isPackageSuspended()
725 */
726 public @Nullable Bundle getSuspendedPackageLauncherExtras(String packageName, UserHandle user) {
727 logErrorForInvalidProfileAccess(user);
728 try {
729 return mService.getSuspendedPackageLauncherExtras(packageName, user);
730 } catch (RemoteException re) {
731 throw re.rethrowFromSystemServer();
732 }
733 }
734
735 /**
Suprabh Shukla79000492018-12-24 17:03:02 -0800736 * Returns whether a package should be hidden from suggestions to the user. Currently, this
737 * could be done because the package was marked as distracting to the user via
738 * {@code PackageManager.setDistractingPackageRestrictions(String[], int)}.
739 *
740 * @param packageName The package for which to check.
741 * @param user the {@link UserHandle} of the profile.
742 * @return
743 */
744 public boolean shouldHideFromSuggestions(@NonNull String packageName,
745 @NonNull UserHandle user) {
746 Preconditions.checkNotNull(packageName, "packageName");
747 Preconditions.checkNotNull(user, "user");
748 try {
749 return mService.shouldHideFromSuggestions(packageName, user);
750 } catch (RemoteException re) {
751 throw re.rethrowFromSystemServer();
752 }
753 }
754
755 /**
Benjamin Miller7afa84c2017-07-17 13:01:35 +0200756 * Returns {@link ApplicationInfo} about an application installed for a specific user profile.
Kenny Guy77242752016-01-15 13:29:06 +0000757 *
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700758 * @param packageName The package name of the application
Kenny Guy77242752016-01-15 13:29:06 +0000759 * @param flags Additional option flags {@link PackageManager#getApplicationInfo}
760 * @param user The UserHandle of the profile.
761 *
Benjamin Miller7afa84c2017-07-17 13:01:35 +0200762 * @return {@link ApplicationInfo} containing information about the package. Returns
763 * {@code null} if the package isn't installed for the given profile, or the profile
764 * isn't enabled.
Kenny Guy77242752016-01-15 13:29:06 +0000765 */
Makoto Onuki7c7fbf62017-04-14 11:03:56 -0700766 public ApplicationInfo getApplicationInfo(@NonNull String packageName,
767 @ApplicationInfoFlags int flags, @NonNull UserHandle user)
768 throws PackageManager.NameNotFoundException {
769 Preconditions.checkNotNull(packageName, "packageName");
Suprabh Shukla19b41f32018-03-26 22:35:13 -0700770 Preconditions.checkNotNull(user, "user");
Makoto Onukide3c16c2017-01-26 11:39:31 -0800771 logErrorForInvalidProfileAccess(user);
Kenny Guy77242752016-01-15 13:29:06 +0000772 try {
Makoto Onuki7c7fbf62017-04-14 11:03:56 -0700773 final ApplicationInfo ai = mService
774 .getApplicationInfo(mContext.getPackageName(), packageName, flags, user);
775 if (ai == null) {
776 throw new NameNotFoundException("Package " + packageName + " not found for user "
777 + user.getIdentifier());
778 }
779 return ai;
Kenny Guy77242752016-01-15 13:29:06 +0000780 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700781 throw re.rethrowFromSystemServer();
Kenny Guy77242752016-01-15 13:29:06 +0000782 }
783 }
784
785 /**
Varun Shah2546cef2019-01-11 15:50:54 -0800786 * Returns an object describing the app usage limit for the given package.
787 * If there are multiple limits that apply to the package, the one with the smallest
788 * time remaining will be returned.
789 *
790 * @param packageName name of the package whose app usage limit will be returned
791 * @param user the user of the package
792 *
793 * @return an {@link AppUsageLimit} object describing the app time limit containing
794 * the given package with the smallest time remaining, or {@code null} if none exist.
795 * @throws SecurityException when the caller is not the active launcher.
796 */
797 @Nullable
Varun Shah2c9263c2019-02-15 10:51:10 -0800798 public LauncherApps.AppUsageLimit getAppUsageLimit(@NonNull String packageName,
799 @NonNull UserHandle user) {
Varun Shah2546cef2019-01-11 15:50:54 -0800800 try {
801 return mService.getAppUsageLimit(mContext.getPackageName(), packageName, user);
802 } catch (RemoteException re) {
803 throw re.rethrowFromSystemServer();
804 }
805 }
806
807 /**
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100808 * Checks if the activity exists and it enabled for a profile.
809 *
Makoto Onuki516020a2019-01-28 14:16:42 -0800810 * <p>The activity may still not be exported, in which case {@link #startMainActivity} will
811 * throw a {@link SecurityException} unless the caller has the same UID as the target app's.
812 *
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100813 * @param component The activity to check.
814 * @param user The UserHandle of the profile.
815 *
816 * @return true if the activity exists and is enabled.
817 */
Kenny Guyf939dba2014-08-15 15:32:34 +0100818 public boolean isActivityEnabled(ComponentName component, UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800819 logErrorForInvalidProfileAccess(user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100820 try {
Makoto Onuki3a2541e2017-01-24 09:00:15 -0800821 return mService.isActivityEnabled(mContext.getPackageName(), component, user);
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100822 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -0700823 throw re.rethrowFromSystemServer();
Kenny Guy53fa4ec2014-04-29 14:24:18 +0100824 }
825 }
826
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800827 /**
Dianne Hackbornc160fa42017-11-01 16:14:26 -0700828 * Returns whether the caller can access the shortcut information. Access is currently
829 * available to:
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800830 *
Dianne Hackbornc160fa42017-11-01 16:14:26 -0700831 * <ul>
832 * <li>The current launcher (or default launcher if there is no set current launcher).</li>
833 * <li>The currently active voice interaction service.</li>
834 * </ul>
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800835 *
Makoto Onuki4a910962016-07-07 13:57:34 -0700836 * <p>Note when this method returns {@code false}, it may be a temporary situation because
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800837 * the user is trying a new launcher application. The user may decide to change the default
Makoto Onuki4a910962016-07-07 13:57:34 -0700838 * launcher back to the calling application again, so even if a launcher application loses
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800839 * this permission, it does <b>not</b> have to purge pinned shortcut information.
Makoto Onukife9c9662016-07-25 15:12:23 -0700840 * If the calling launcher application contains pinned shortcuts, they will still work,
841 * even though the caller no longer has the shortcut host permission.
Makoto Onuki4a910962016-07-07 13:57:34 -0700842 *
Makoto Onuki02f338e2016-07-29 09:40:40 -0700843 * @throws IllegalStateException when the user is locked.
Makoto Onuki9c850012016-07-26 15:50:50 -0700844 *
Makoto Onuki4a910962016-07-07 13:57:34 -0700845 * @see ShortcutManager
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800846 */
847 public boolean hasShortcutHostPermission() {
848 try {
849 return mService.hasShortcutHostPermission(mContext.getPackageName());
850 } catch (RemoteException re) {
851 throw re.rethrowFromSystemServer();
852 }
853 }
854
Makoto Onukib1588c02017-10-12 15:11:45 -0700855 private List<ShortcutInfo> maybeUpdateDisabledMessage(List<ShortcutInfo> shortcuts) {
856 if (shortcuts == null) {
857 return null;
858 }
859 for (int i = shortcuts.size() - 1; i >= 0; i--) {
860 final ShortcutInfo si = shortcuts.get(i);
861 final String message = ShortcutInfo.getDisabledReasonForRestoreIssue(mContext,
862 si.getDisabledReason());
863 if (message != null) {
864 si.setDisabledMessage(message);
865 }
866 }
867 return shortcuts;
868 }
869
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800870 /**
Makoto Onuki4a910962016-07-07 13:57:34 -0700871 * Returns {@link ShortcutInfo}s that match {@code query}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800872 *
Makoto Onuki2d5b4652016-03-11 16:09:54 -0800873 * <p>Callers must be allowed to access the shortcut information, as defined in {@link
874 * #hasShortcutHostPermission()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800875 *
876 * @param query result includes shortcuts matching this query.
877 * @param user The UserHandle of the profile.
878 *
879 * @return the IDs of {@link ShortcutInfo}s that match the query.
Makoto Onuki02f338e2016-07-29 09:40:40 -0700880 * @throws IllegalStateException when the user is locked, or when the {@code user} user
881 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -0700882 *
883 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800884 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800885 @Nullable
886 public List<ShortcutInfo> getShortcuts(@NonNull ShortcutQuery query,
887 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800888 logErrorForInvalidProfileAccess(user);
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800889 try {
Makoto Onukib1588c02017-10-12 15:11:45 -0700890 // Note this is the only case we need to update the disabled message for shortcuts
891 // that weren't restored.
892 // The restore problem messages are only shown by the user, and publishers will never
893 // see them. The only other API that the launcher gets shortcuts is the shortcut
894 // changed callback, but that only returns shortcuts with the "key" information, so
895 // that won't return disabled message.
896 return maybeUpdateDisabledMessage(mService.getShortcuts(mContext.getPackageName(),
Makoto Onukiabe84422016-04-07 09:41:19 -0700897 query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
Makoto Onuki99302b52017-03-29 12:42:26 -0700898 query.mQueryFlags, user)
Makoto Onukib1588c02017-10-12 15:11:45 -0700899 .getList());
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800900 } catch (RemoteException e) {
901 throw e.rethrowFromSystemServer();
902 }
903 }
904
905 /**
Makoto Onukiabe84422016-04-07 09:41:19 -0700906 * @hide // No longer used. Use getShortcuts() instead. Kept for unit tests.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800907 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800908 @Nullable
Makoto Onukib5a012f2016-06-21 11:13:53 -0700909 @Deprecated
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800910 public List<ShortcutInfo> getShortcutInfo(@NonNull String packageName,
911 @NonNull List<String> ids, @NonNull UserHandle user) {
Makoto Onukiabe84422016-04-07 09:41:19 -0700912 final ShortcutQuery q = new ShortcutQuery();
913 q.setPackage(packageName);
914 q.setShortcutIds(ids);
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700915 q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
Makoto Onukiabe84422016-04-07 09:41:19 -0700916 return getShortcuts(q, user);
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800917 }
918
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800919 /**
920 * Pin shortcuts on a package.
921 *
922 * <p>This API is <b>NOT</b> cumulative; this will replace all pinned shortcuts for the package.
923 * However, different launchers may have different set of pinned shortcuts.
924 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700925 * <p>The calling launcher application must be allowed to access the shortcut information,
926 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800927 *
928 * @param packageName The target package name.
929 * @param shortcutIds The IDs of the shortcut to be pinned.
930 * @param user The UserHandle of the profile.
Makoto Onuki02f338e2016-07-29 09:40:40 -0700931 * @throws IllegalStateException when the user is locked, or when the {@code user} user
932 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -0700933 *
934 * @see ShortcutManager
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800935 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800936 public void pinShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
937 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -0800938 logErrorForInvalidProfileAccess(user);
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800939 try {
940 mService.pinShortcuts(mContext.getPackageName(), packageName, shortcutIds, user);
941 } catch (RemoteException e) {
942 throw e.rethrowFromSystemServer();
943 }
944 }
945
946 /**
Makoto Onukib6d35232016-04-04 15:57:17 -0700947 * @hide kept for testing.
Makoto Onukiabe84422016-04-07 09:41:19 -0700948 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700949 @Deprecated
Makoto Onukiabe84422016-04-07 09:41:19 -0700950 public int getShortcutIconResId(@NonNull ShortcutInfo shortcut) {
Makoto Onukib6d35232016-04-04 15:57:17 -0700951 return shortcut.getIconResourceId();
Makoto Onukiabe84422016-04-07 09:41:19 -0700952 }
953
954 /**
Makoto Onukib6d35232016-04-04 15:57:17 -0700955 * @hide kept for testing.
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800956 */
Makoto Onukib5a012f2016-06-21 11:13:53 -0700957 @Deprecated
Makoto Onukiabe84422016-04-07 09:41:19 -0700958 public int getShortcutIconResId(@NonNull String packageName, @NonNull String shortcutId,
959 @NonNull UserHandle user) {
Makoto Onukib6d35232016-04-04 15:57:17 -0700960 final ShortcutQuery q = new ShortcutQuery();
961 q.setPackage(packageName);
962 q.setShortcutIds(Arrays.asList(shortcutId));
Makoto Onuki4d6b87f2016-06-17 13:47:40 -0700963 q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
Makoto Onukib6d35232016-04-04 15:57:17 -0700964 final List<ShortcutInfo> shortcuts = getShortcuts(q, user);
Makoto Onukiabe84422016-04-07 09:41:19 -0700965
Makoto Onukib6d35232016-04-04 15:57:17 -0700966 return shortcuts.size() > 0 ? shortcuts.get(0).getIconResourceId() : 0;
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800967 }
968
969 /**
Makoto Onukib5a012f2016-06-21 11:13:53 -0700970 * @hide internal/unit tests only
Makoto Onukiabe84422016-04-07 09:41:19 -0700971 */
972 public ParcelFileDescriptor getShortcutIconFd(
973 @NonNull ShortcutInfo shortcut) {
Makoto Onuki22fcc682016-05-17 14:52:19 -0700974 return getShortcutIconFd(shortcut.getPackage(), shortcut.getId(),
Makoto Onukiabe84422016-04-07 09:41:19 -0700975 shortcut.getUserId());
976 }
977
978 /**
Makoto Onukib5a012f2016-06-21 11:13:53 -0700979 * @hide internal/unit tests only
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800980 */
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800981 public ParcelFileDescriptor getShortcutIconFd(
Makoto Onukiabe84422016-04-07 09:41:19 -0700982 @NonNull String packageName, @NonNull String shortcutId, @NonNull UserHandle user) {
983 return getShortcutIconFd(packageName, shortcutId, user.getIdentifier());
984 }
985
986 private ParcelFileDescriptor getShortcutIconFd(
987 @NonNull String packageName, @NonNull String shortcutId, int userId) {
Makoto Onuki55046222016-03-08 10:49:47 -0800988 try {
Makoto Onukiabe84422016-04-07 09:41:19 -0700989 return mService.getShortcutIconFd(mContext.getPackageName(),
990 packageName, shortcutId, userId);
Makoto Onuki55046222016-03-08 10:49:47 -0800991 } catch (RemoteException e) {
992 throw e.rethrowFromSystemServer();
993 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -0800994 }
995
Makoto Onuki04b9aab2016-05-23 17:13:30 -0700996 /**
997 * Returns the icon for this shortcut, without any badging for the profile.
998 *
Makoto Onukife9c9662016-07-25 15:12:23 -0700999 * <p>The calling launcher application must be allowed to access the shortcut information,
1000 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki4a910962016-07-07 13:57:34 -07001001 *
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001002 * @param density The preferred density of the icon, zero for default density. Use
1003 * density DPI values from {@link DisplayMetrics}.
Makoto Onuki4a910962016-07-07 13:57:34 -07001004 *
1005 * @return The drawable associated with the shortcut.
Makoto Onuki02f338e2016-07-29 09:40:40 -07001006 * @throws IllegalStateException when the user is locked, or when the {@code user} user
1007 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -07001008 *
1009 * @see ShortcutManager
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001010 * @see #getShortcutBadgedIconDrawable(ShortcutInfo, int)
1011 * @see DisplayMetrics
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001012 */
1013 public Drawable getShortcutIconDrawable(@NonNull ShortcutInfo shortcut, int density) {
1014 if (shortcut.hasIconFile()) {
1015 final ParcelFileDescriptor pfd = getShortcutIconFd(shortcut);
1016 if (pfd == null) {
1017 return null;
1018 }
1019 try {
1020 final Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
Hyunyoung Songf281e7a2017-02-13 10:57:42 -08001021 if (bmp != null) {
1022 BitmapDrawable dr = new BitmapDrawable(mContext.getResources(), bmp);
Hyunyoung Songe4179e22017-03-01 12:51:26 -08001023 if (shortcut.hasAdaptiveBitmap()) {
Hyunyoung Songbe8835e2017-02-17 11:25:08 -08001024 return new AdaptiveIconDrawable(null, dr);
Hyunyoung Songf281e7a2017-02-13 10:57:42 -08001025 } else {
1026 return dr;
1027 }
1028 }
1029 return null;
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001030 } finally {
1031 try {
1032 pfd.close();
1033 } catch (IOException ignore) {
1034 }
1035 }
1036 } else if (shortcut.hasIconResource()) {
Makoto Onuki2d895c32016-12-02 15:48:40 -08001037 return loadDrawableResourceFromPackage(shortcut.getPackage(),
1038 shortcut.getIconResourceId(), shortcut.getUserHandle(), density);
1039 } else if (shortcut.getIcon() != null) {
1040 // This happens if a shortcut is pending-approval.
1041 final Icon icon = shortcut.getIcon();
1042 switch (icon.getType()) {
1043 case Icon.TYPE_RESOURCE: {
1044 return loadDrawableResourceFromPackage(shortcut.getPackage(),
1045 icon.getResId(), shortcut.getUserHandle(), density);
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001046 }
Hyunyoung Songf281e7a2017-02-13 10:57:42 -08001047 case Icon.TYPE_BITMAP:
Hyunyoung Songe4179e22017-03-01 12:51:26 -08001048 case Icon.TYPE_ADAPTIVE_BITMAP: {
Makoto Onuki2d895c32016-12-02 15:48:40 -08001049 return icon.loadDrawable(mContext);
1050 }
1051 default:
1052 return null; // Shouldn't happen though.
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001053 }
1054 } else {
1055 return null; // Has no icon.
1056 }
Makoto Onuki20c95f82016-05-11 16:51:01 -07001057 }
1058
Makoto Onuki2d895c32016-12-02 15:48:40 -08001059 private Drawable loadDrawableResourceFromPackage(String packageName, int resId,
1060 UserHandle user, int density) {
1061 try {
1062 if (resId == 0) {
1063 return null; // Shouldn't happen but just in case.
1064 }
1065 final ApplicationInfo ai = getApplicationInfo(packageName, /* flags =*/ 0, user);
1066 final Resources res = mContext.getPackageManager().getResourcesForApplication(ai);
1067 return res.getDrawableForDensity(resId, density);
1068 } catch (NameNotFoundException | Resources.NotFoundException e) {
1069 return null;
1070 }
1071 }
1072
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001073 /**
1074 * Returns the shortcut icon with badging appropriate for the profile.
1075 *
Makoto Onukife9c9662016-07-25 15:12:23 -07001076 * <p>The calling launcher application must be allowed to access the shortcut information,
1077 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki4a910962016-07-07 13:57:34 -07001078 *
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001079 * @param density Optional density for the icon, or 0 to use the default density. Use
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001080 * @return A badged icon for the shortcut.
Makoto Onuki02f338e2016-07-29 09:40:40 -07001081 * @throws IllegalStateException when the user is locked, or when the {@code user} user
1082 * is locked or not running.
Makoto Onuki4a910962016-07-07 13:57:34 -07001083 *
1084 * @see ShortcutManager
Makoto Onukife9c9662016-07-25 15:12:23 -07001085 * @see #getShortcutIconDrawable(ShortcutInfo, int)
Makoto Onuki4a910962016-07-07 13:57:34 -07001086 * @see DisplayMetrics
Makoto Onuki04b9aab2016-05-23 17:13:30 -07001087 */
1088 public Drawable getShortcutBadgedIconDrawable(ShortcutInfo shortcut, int density) {
1089 final Drawable originalIcon = getShortcutIconDrawable(shortcut, density);
1090
1091 return (originalIcon == null) ? null : mContext.getPackageManager().getUserBadgedIcon(
1092 originalIcon, shortcut.getUserHandle());
Makoto Onuki20c95f82016-05-11 16:51:01 -07001093 }
1094
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001095 /**
Makoto Onuki4a910962016-07-07 13:57:34 -07001096 * Starts a shortcut.
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001097 *
Makoto Onukife9c9662016-07-25 15:12:23 -07001098 * <p>The calling launcher application must be allowed to access the shortcut information,
1099 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001100 *
Makoto Onuki43204b82016-03-08 16:16:44 -08001101 * @param packageName The target shortcut package name.
1102 * @param shortcutId The target shortcut ID.
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001103 * @param sourceBounds The Rect containing the source bounds of the clicked icon.
1104 * @param startActivityOptions Options to pass to startActivity.
1105 * @param user The UserHandle of the profile.
Makoto Onuki02f338e2016-07-29 09:40:40 -07001106 * @throws IllegalStateException when the user is locked, or when the {@code user} user
1107 * is locked or not running.
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001108 *
1109 * @throws android.content.ActivityNotFoundException failed to start shortcut. (e.g.
1110 * the shortcut no longer exists, is disabled, the intent receiver activity doesn't exist, etc)
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001111 */
Makoto Onukid6880792016-06-29 13:37:43 -07001112 public void startShortcut(@NonNull String packageName, @NonNull String shortcutId,
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001113 @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
1114 @NonNull UserHandle user) {
Makoto Onukide3c16c2017-01-26 11:39:31 -08001115 logErrorForInvalidProfileAccess(user);
1116
Makoto Onukid6880792016-06-29 13:37:43 -07001117 startShortcut(packageName, shortcutId, sourceBounds, startActivityOptions,
Makoto Onukiabe84422016-04-07 09:41:19 -07001118 user.getIdentifier());
1119 }
1120
1121 /**
1122 * Launches a shortcut.
1123 *
Makoto Onukife9c9662016-07-25 15:12:23 -07001124 * <p>The calling launcher application must be allowed to access the shortcut information,
1125 * as defined in {@link #hasShortcutHostPermission()}.
Makoto Onukiabe84422016-04-07 09:41:19 -07001126 *
1127 * @param shortcut The target shortcut.
1128 * @param sourceBounds The Rect containing the source bounds of the clicked icon.
1129 * @param startActivityOptions Options to pass to startActivity.
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 Onukiabe84422016-04-07 09:41:19 -07001135 */
Makoto Onukid6880792016-06-29 13:37:43 -07001136 public void startShortcut(@NonNull ShortcutInfo shortcut,
Makoto Onukiabe84422016-04-07 09:41:19 -07001137 @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions) {
Makoto Onukid6880792016-06-29 13:37:43 -07001138 startShortcut(shortcut.getPackage(), shortcut.getId(),
Makoto Onukiabe84422016-04-07 09:41:19 -07001139 sourceBounds, startActivityOptions,
1140 shortcut.getUserId());
1141 }
1142
Mathew Inwood5c0d3542018-08-14 13:54:31 +01001143 @UnsupportedAppUsage
Makoto Onukid6880792016-06-29 13:37:43 -07001144 private void startShortcut(@NonNull String packageName, @NonNull String shortcutId,
Makoto Onukiabe84422016-04-07 09:41:19 -07001145 @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
1146 int userId) {
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001147 try {
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001148 final boolean success =
1149 mService.startShortcut(mContext.getPackageName(), packageName, shortcutId,
Makoto Onukiabe84422016-04-07 09:41:19 -07001150 sourceBounds, startActivityOptions, userId);
Makoto Onuki83f6d2d2016-07-11 14:30:19 -07001151 if (!success) {
1152 throw new ActivityNotFoundException("Shortcut could not be started");
1153 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001154 } catch (RemoteException e) {
1155 throw e.rethrowFromSystemServer();
1156 }
1157 }
Kenny Guy53fa4ec2014-04-29 14:24:18 +01001158
1159 /**
Jon Miranda2b340a22019-01-25 14:03:49 -08001160 * Registers a callback for changes to packages in this user and managed profiles.
Kenny Guyc01545372014-06-16 14:17:26 +01001161 *
Kenny Guy10a574f2014-08-26 16:17:58 +01001162 * @param callback The callback to register.
Kenny Guyc01545372014-06-16 14:17:26 +01001163 */
Kenny Guy10a574f2014-08-26 16:17:58 +01001164 public void registerCallback(Callback callback) {
1165 registerCallback(callback, null);
Kenny Guyb42c89b2014-07-28 19:20:07 +01001166 }
1167
1168 /**
Jon Miranda2b340a22019-01-25 14:03:49 -08001169 * Registers a callback for changes to packages in this user and managed profiles.
Kenny Guyb42c89b2014-07-28 19:20:07 +01001170 *
Kenny Guy10a574f2014-08-26 16:17:58 +01001171 * @param callback The callback to register.
Kenny Guyb42c89b2014-07-28 19:20:07 +01001172 * @param handler that should be used to post callbacks on, may be null.
1173 */
Kenny Guy10a574f2014-08-26 16:17:58 +01001174 public void registerCallback(Callback callback, Handler handler) {
Kenny Guyc01545372014-06-16 14:17:26 +01001175 synchronized (this) {
Kenny Guy172a2162015-06-19 17:21:28 +01001176 if (callback != null && findCallbackLocked(callback) < 0) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001177 boolean addedFirstCallback = mCallbacks.size() == 0;
1178 addCallbackLocked(callback, handler);
1179 if (addedFirstCallback) {
Kenny Guyc01545372014-06-16 14:17:26 +01001180 try {
Makoto Onuki4dbe0de2016-03-14 17:31:49 -07001181 mService.addOnAppsChangedListener(mContext.getPackageName(),
1182 mAppsChangedListener);
Kenny Guyc01545372014-06-16 14:17:26 +01001183 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001184 throw re.rethrowFromSystemServer();
Kenny Guyc01545372014-06-16 14:17:26 +01001185 }
1186 }
1187 }
1188 }
1189 }
1190
1191 /**
Kenny Guy10a574f2014-08-26 16:17:58 +01001192 * Unregisters a callback that was previously registered.
Kenny Guyc01545372014-06-16 14:17:26 +01001193 *
Kenny Guy10a574f2014-08-26 16:17:58 +01001194 * @param callback The callback to unregister.
1195 * @see #registerCallback(Callback)
Kenny Guyc01545372014-06-16 14:17:26 +01001196 */
Kenny Guy10a574f2014-08-26 16:17:58 +01001197 public void unregisterCallback(Callback callback) {
Kenny Guyc01545372014-06-16 14:17:26 +01001198 synchronized (this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001199 removeCallbackLocked(callback);
Kenny Guy44b6dee2014-07-10 18:10:14 +01001200 if (mCallbacks.size() == 0) {
Amith Yamasanie781c812014-05-28 15:28:18 -07001201 try {
1202 mService.removeOnAppsChangedListener(mAppsChangedListener);
1203 } catch (RemoteException re) {
Jeff Sharkeyf8880562016-02-26 13:03:01 -07001204 throw re.rethrowFromSystemServer();
Amith Yamasanie781c812014-05-28 15:28:18 -07001205 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001206 }
1207 }
1208 }
1209
Kenny Guy172a2162015-06-19 17:21:28 +01001210 /** @return position in mCallbacks for callback or -1 if not present. */
1211 private int findCallbackLocked(Callback callback) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001212 if (callback == null) {
1213 throw new IllegalArgumentException("Callback cannot be null");
1214 }
1215 final int size = mCallbacks.size();
1216 for (int i = 0; i < size; ++i) {
1217 if (mCallbacks.get(i).mCallback == callback) {
Kenny Guy172a2162015-06-19 17:21:28 +01001218 return i;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001219 }
1220 }
Kenny Guy172a2162015-06-19 17:21:28 +01001221 return -1;
1222 }
1223
1224 private void removeCallbackLocked(Callback callback) {
1225 int pos = findCallbackLocked(callback);
1226 if (pos >= 0) {
1227 mCallbacks.remove(pos);
1228 }
Kenny Guyb42c89b2014-07-28 19:20:07 +01001229 }
1230
Kenny Guyf939dba2014-08-15 15:32:34 +01001231 private void addCallbackLocked(Callback callback, Handler handler) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001232 // Remove if already present.
1233 removeCallbackLocked(callback);
1234 if (handler == null) {
1235 handler = new Handler();
1236 }
1237 CallbackMessageHandler toAdd = new CallbackMessageHandler(handler.getLooper(), callback);
1238 mCallbacks.add(toAdd);
1239 }
1240
Amith Yamasani4f582632014-02-19 14:31:52 -08001241 private IOnAppsChangedListener.Stub mAppsChangedListener = new IOnAppsChangedListener.Stub() {
1242
1243 @Override
Kenny Guyb42c89b2014-07-28 19:20:07 +01001244 public void onPackageRemoved(UserHandle user, String packageName)
1245 throws RemoteException {
Amith Yamasani4f582632014-02-19 14:31:52 -08001246 if (DEBUG) {
1247 Log.d(TAG, "onPackageRemoved " + user.getIdentifier() + "," + packageName);
1248 }
1249 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001250 for (CallbackMessageHandler callback : mCallbacks) {
1251 callback.postOnPackageRemoved(packageName, user);
Kenny Guyc01545372014-06-16 14:17:26 +01001252 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001253 }
1254 }
1255
1256 @Override
1257 public void onPackageChanged(UserHandle user, String packageName) throws RemoteException {
1258 if (DEBUG) {
1259 Log.d(TAG, "onPackageChanged " + user.getIdentifier() + "," + packageName);
1260 }
1261 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001262 for (CallbackMessageHandler callback : mCallbacks) {
1263 callback.postOnPackageChanged(packageName, user);
Kenny Guyc01545372014-06-16 14:17:26 +01001264 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001265 }
1266 }
1267
1268 @Override
1269 public void onPackageAdded(UserHandle user, String packageName) throws RemoteException {
1270 if (DEBUG) {
1271 Log.d(TAG, "onPackageAdded " + user.getIdentifier() + "," + packageName);
1272 }
1273 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001274 for (CallbackMessageHandler callback : mCallbacks) {
1275 callback.postOnPackageAdded(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 onPackagesAvailable(UserHandle user, String[] packageNames, boolean replacing)
1282 throws RemoteException {
1283 if (DEBUG) {
1284 Log.d(TAG, "onPackagesAvailable " + user.getIdentifier() + "," + packageNames);
1285 }
1286 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001287 for (CallbackMessageHandler callback : mCallbacks) {
1288 callback.postOnPackagesAvailable(packageNames, user, replacing);
Kenny Guyc01545372014-06-16 14:17:26 +01001289 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001290 }
1291 }
1292
1293 @Override
1294 public void onPackagesUnavailable(UserHandle user, String[] packageNames, boolean replacing)
1295 throws RemoteException {
1296 if (DEBUG) {
1297 Log.d(TAG, "onPackagesUnavailable " + user.getIdentifier() + "," + packageNames);
1298 }
1299 synchronized (LauncherApps.this) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001300 for (CallbackMessageHandler callback : mCallbacks) {
1301 callback.postOnPackagesUnavailable(packageNames, user, replacing);
Kenny Guyc01545372014-06-16 14:17:26 +01001302 }
Kenny Guy77242752016-01-15 13:29:06 +00001303 }
1304 }
1305
1306 @Override
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001307 public void onPackagesSuspended(UserHandle user, String[] packageNames,
1308 Bundle launcherExtras)
Kenny Guy77242752016-01-15 13:29:06 +00001309 throws RemoteException {
1310 if (DEBUG) {
1311 Log.d(TAG, "onPackagesSuspended " + user.getIdentifier() + "," + packageNames);
1312 }
1313 synchronized (LauncherApps.this) {
1314 for (CallbackMessageHandler callback : mCallbacks) {
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001315 callback.postOnPackagesSuspended(packageNames, launcherExtras, user);
Kenny Guy77242752016-01-15 13:29:06 +00001316 }
1317 }
1318 }
1319
1320 @Override
1321 public void onPackagesUnsuspended(UserHandle user, String[] packageNames)
1322 throws RemoteException {
1323 if (DEBUG) {
1324 Log.d(TAG, "onPackagesUnsuspended " + user.getIdentifier() + "," + packageNames);
1325 }
1326 synchronized (LauncherApps.this) {
1327 for (CallbackMessageHandler callback : mCallbacks) {
1328 callback.postOnPackagesUnsuspended(packageNames, user);
1329 }
1330 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001331 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001332
1333 @Override
1334 public void onShortcutChanged(UserHandle user, String packageName,
1335 ParceledListSlice shortcuts) {
1336 if (DEBUG) {
1337 Log.d(TAG, "onShortcutChanged " + user.getIdentifier() + "," + packageName);
1338 }
1339 final List<ShortcutInfo> list = shortcuts.getList();
1340 synchronized (LauncherApps.this) {
1341 for (CallbackMessageHandler callback : mCallbacks) {
1342 callback.postOnShortcutChanged(packageName, user, list);
1343 }
1344 }
1345 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001346 };
Kenny Guyb42c89b2014-07-28 19:20:07 +01001347
1348 private static class CallbackMessageHandler extends Handler {
1349 private static final int MSG_ADDED = 1;
1350 private static final int MSG_REMOVED = 2;
1351 private static final int MSG_CHANGED = 3;
1352 private static final int MSG_AVAILABLE = 4;
1353 private static final int MSG_UNAVAILABLE = 5;
Kenny Guy77242752016-01-15 13:29:06 +00001354 private static final int MSG_SUSPENDED = 6;
1355 private static final int MSG_UNSUSPENDED = 7;
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001356 private static final int MSG_SHORTCUT_CHANGED = 8;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001357
Kenny Guyf939dba2014-08-15 15:32:34 +01001358 private LauncherApps.Callback mCallback;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001359
1360 private static class CallbackInfo {
1361 String[] packageNames;
1362 String packageName;
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001363 Bundle launcherExtras;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001364 boolean replacing;
1365 UserHandle user;
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001366 List<ShortcutInfo> shortcuts;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001367 }
1368
Kenny Guyf939dba2014-08-15 15:32:34 +01001369 public CallbackMessageHandler(Looper looper, LauncherApps.Callback callback) {
Kenny Guyb42c89b2014-07-28 19:20:07 +01001370 super(looper, null, true);
1371 mCallback = callback;
1372 }
1373
1374 @Override
1375 public void handleMessage(Message msg) {
1376 if (mCallback == null || !(msg.obj instanceof CallbackInfo)) {
1377 return;
1378 }
1379 CallbackInfo info = (CallbackInfo) msg.obj;
1380 switch (msg.what) {
1381 case MSG_ADDED:
1382 mCallback.onPackageAdded(info.packageName, info.user);
1383 break;
1384 case MSG_REMOVED:
1385 mCallback.onPackageRemoved(info.packageName, info.user);
1386 break;
1387 case MSG_CHANGED:
1388 mCallback.onPackageChanged(info.packageName, info.user);
1389 break;
1390 case MSG_AVAILABLE:
1391 mCallback.onPackagesAvailable(info.packageNames, info.user, info.replacing);
1392 break;
1393 case MSG_UNAVAILABLE:
1394 mCallback.onPackagesUnavailable(info.packageNames, info.user, info.replacing);
1395 break;
Kenny Guy77242752016-01-15 13:29:06 +00001396 case MSG_SUSPENDED:
Suprabh Shukla96212bc2018-04-10 15:04:51 -07001397 mCallback.onPackagesSuspended(info.packageNames, info.user, info.launcherExtras
1398 );
Kenny Guy77242752016-01-15 13:29:06 +00001399 break;
1400 case MSG_UNSUSPENDED:
1401 mCallback.onPackagesUnsuspended(info.packageNames, info.user);
1402 break;
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001403 case MSG_SHORTCUT_CHANGED:
1404 mCallback.onShortcutsChanged(info.packageName, info.shortcuts, info.user);
1405 break;
Kenny Guyb42c89b2014-07-28 19:20:07 +01001406 }
1407 }
1408
1409 public void postOnPackageAdded(String packageName, UserHandle user) {
1410 CallbackInfo info = new CallbackInfo();
1411 info.packageName = packageName;
1412 info.user = user;
1413 obtainMessage(MSG_ADDED, info).sendToTarget();
1414 }
1415
1416 public void postOnPackageRemoved(String packageName, UserHandle user) {
1417 CallbackInfo info = new CallbackInfo();
1418 info.packageName = packageName;
1419 info.user = user;
1420 obtainMessage(MSG_REMOVED, info).sendToTarget();
1421 }
1422
1423 public void postOnPackageChanged(String packageName, UserHandle user) {
1424 CallbackInfo info = new CallbackInfo();
1425 info.packageName = packageName;
1426 info.user = user;
1427 obtainMessage(MSG_CHANGED, info).sendToTarget();
1428 }
1429
1430 public void postOnPackagesAvailable(String[] packageNames, UserHandle user,
1431 boolean replacing) {
1432 CallbackInfo info = new CallbackInfo();
1433 info.packageNames = packageNames;
1434 info.replacing = replacing;
1435 info.user = user;
1436 obtainMessage(MSG_AVAILABLE, info).sendToTarget();
1437 }
1438
1439 public void postOnPackagesUnavailable(String[] packageNames, UserHandle user,
1440 boolean replacing) {
1441 CallbackInfo info = new CallbackInfo();
1442 info.packageNames = packageNames;
1443 info.replacing = replacing;
1444 info.user = user;
1445 obtainMessage(MSG_UNAVAILABLE, info).sendToTarget();
1446 }
Kenny Guy77242752016-01-15 13:29:06 +00001447
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001448 public void postOnPackagesSuspended(String[] packageNames, Bundle launcherExtras,
1449 UserHandle user) {
Kenny Guy77242752016-01-15 13:29:06 +00001450 CallbackInfo info = new CallbackInfo();
1451 info.packageNames = packageNames;
1452 info.user = user;
Suprabh Shukla19b41f32018-03-26 22:35:13 -07001453 info.launcherExtras = launcherExtras;
Kenny Guy77242752016-01-15 13:29:06 +00001454 obtainMessage(MSG_SUSPENDED, info).sendToTarget();
1455 }
1456
1457 public void postOnPackagesUnsuspended(String[] packageNames, UserHandle user) {
1458 CallbackInfo info = new CallbackInfo();
1459 info.packageNames = packageNames;
1460 info.user = user;
1461 obtainMessage(MSG_UNSUSPENDED, info).sendToTarget();
1462 }
Makoto Onuki6f7362d92016-03-04 13:39:41 -08001463
1464 public void postOnShortcutChanged(String packageName, UserHandle user,
1465 List<ShortcutInfo> shortcuts) {
1466 CallbackInfo info = new CallbackInfo();
1467 info.packageName = packageName;
1468 info.user = user;
1469 info.shortcuts = shortcuts;
1470 obtainMessage(MSG_SHORTCUT_CHANGED, info).sendToTarget();
1471 }
Kenny Guyb42c89b2014-07-28 19:20:07 +01001472 }
Makoto Onuki2d895c32016-12-02 15:48:40 -08001473
1474 /**
Jon Miranda2b340a22019-01-25 14:03:49 -08001475 * Register a callback to watch for session lifecycle events in this user and managed profiles.
1476 * @param callback The callback to register.
1477 * @param executor {@link Executor} to handle the callbacks, cannot be null.
1478 *
1479 * @see PackageInstaller#registerSessionCallback(SessionCallback)
1480 */
1481 public void registerPackageInstallerSessionCallback(
1482 @NonNull @CallbackExecutor Executor executor, @NonNull SessionCallback callback) {
1483 if (executor == null) {
1484 throw new NullPointerException("Executor must not be null");
1485 }
1486
1487 synchronized (mDelegates) {
1488 final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
1489 executor);
1490 try {
1491 mService.registerPackageInstallerCallback(mContext.getPackageName(),
1492 delegate);
1493 } catch (RemoteException e) {
1494 throw e.rethrowFromSystemServer();
1495 }
1496 mDelegates.add(delegate);
1497 }
1498 }
1499
1500 /**
1501 * Unregisters a callback that was previously registered.
1502 *
1503 * @param callback The callback to unregister.
1504 * @see #registerPackageInstallerSessionCallback(Executor, SessionCallback)
1505 */
1506 public void unregisterPackageInstallerSessionCallback(SessionCallback callback) {
1507 synchronized (mDelegates) {
1508 for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
1509 final SessionCallbackDelegate delegate = i.next();
1510 if (delegate.mCallback == callback) {
1511 mPm.getPackageInstaller().unregisterSessionCallback(delegate.mCallback);
1512 i.remove();
1513 }
1514 }
1515 }
1516 }
1517
1518 /**
1519 * Return list of all known install sessions in this user and managed profiles, regardless
1520 * of the installer.
1521 *
1522 * @see PackageInstaller#getAllSessions()
1523 */
1524 public @NonNull List<SessionInfo> getAllPackageInstallerSessions() {
1525 try {
1526 return mService.getAllSessions(mContext.getPackageName()).getList();
1527 } catch (RemoteException e) {
1528 throw e.rethrowFromSystemServer();
1529 }
1530 }
1531
1532 /**
Makoto Onuki2d895c32016-12-02 15:48:40 -08001533 * A helper method to extract a {@link PinItemRequest} set to
1534 * the {@link #EXTRA_PIN_ITEM_REQUEST} extra.
1535 */
1536 public PinItemRequest getPinItemRequest(Intent intent) {
1537 return intent.getParcelableExtra(EXTRA_PIN_ITEM_REQUEST);
1538 }
1539
1540 /**
Sunny Goyal7f7372a2017-01-24 11:53:54 -08001541 * Represents a "pin shortcut" or a "pin appwidget" request made by an app, which is sent with
1542 * an {@link #ACTION_CONFIRM_PIN_SHORTCUT} or {@link #ACTION_CONFIRM_PIN_APPWIDGET} intent
1543 * respectively to the default launcher app.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001544 *
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001545 * <h3>Request of the {@link #REQUEST_TYPE_SHORTCUT} type.
Makoto Onuki0c280712017-01-19 15:14:27 -08001546 *
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001547 * <p>A {@link #REQUEST_TYPE_SHORTCUT} request represents a request to pin a
1548 * {@link ShortcutInfo}. If the launcher accepts a request, call {@link #accept()},
1549 * or {@link #accept(Bundle)} with a null or empty Bundle. No options are defined for
1550 * pin-shortcuts requests.
1551 *
1552 * <p>{@link #getShortcutInfo()} always returns a non-null {@link ShortcutInfo} for this type.
1553 *
1554 * <p>The launcher may receive a request with a {@link ShortcutInfo} that is already pinned, in
1555 * which case {@link ShortcutInfo#isPinned()} returns true. This means the user wants to create
1556 * another pinned shortcut for a shortcut that's already pinned. If the launcher accepts it,
1557 * {@link #accept()} must still be called even though the shortcut is already pinned, and
1558 * create a new pinned shortcut icon for it.
1559 *
1560 * <p>See also {@link ShortcutManager} for more details.
1561 *
1562 * <h3>Request of the {@link #REQUEST_TYPE_APPWIDGET} type.
1563 *
1564 * <p>A {@link #REQUEST_TYPE_SHORTCUT} request represents a request to pin a
1565 * an AppWidget. If the launcher accepts a request, call {@link #accept(Bundle)} with
1566 * the appwidget integer ID set to the
1567 * {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID} extra.
1568 *
1569 * <p>{@link #getAppWidgetProviderInfo(Context)} always returns a non-null
1570 * {@link AppWidgetProviderInfo} for this type.
1571 *
1572 * <p>See also {@link AppWidgetManager} for more details.
Sunny Goyal7f7372a2017-01-24 11:53:54 -08001573 *
Makoto Onuki2d895c32016-12-02 15:48:40 -08001574 * @see #EXTRA_PIN_ITEM_REQUEST
1575 * @see #getPinItemRequest(Intent)
1576 */
1577 public static final class PinItemRequest implements Parcelable {
1578
1579 /** This is a request to pin shortcut. */
1580 public static final int REQUEST_TYPE_SHORTCUT = 1;
1581
Sunny Goyal87a563e2017-01-01 19:42:45 -08001582 /** This is a request to pin app widget. */
1583 public static final int REQUEST_TYPE_APPWIDGET = 2;
1584
Makoto Onukif5663b12017-01-09 14:09:56 -08001585 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -07001586 @IntDef(prefix = { "REQUEST_TYPE_" }, value = {
1587 REQUEST_TYPE_SHORTCUT,
1588 REQUEST_TYPE_APPWIDGET
1589 })
Makoto Onuki2d895c32016-12-02 15:48:40 -08001590 @Retention(RetentionPolicy.SOURCE)
1591 public @interface RequestType {}
1592
1593 private final int mRequestType;
Makoto Onuki2d895c32016-12-02 15:48:40 -08001594 private final IPinItemRequest mInner;
1595
1596 /**
1597 * @hide
1598 */
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001599 public PinItemRequest(IPinItemRequest inner, int type) {
Sunny Goyal87a563e2017-01-01 19:42:45 -08001600 mInner = inner;
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001601 mRequestType = type;
Makoto Onuki2d895c32016-12-02 15:48:40 -08001602 }
1603
1604 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001605 * Represents the type of a request, which is one of the {@code REQUEST_TYPE_} constants.
1606 *
1607 * @return one of the {@code REQUEST_TYPE_} constants.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001608 */
1609 @RequestType
1610 public int getRequestType() {
1611 return mRequestType;
1612 }
1613
1614 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001615 * {@link ShortcutInfo} sent by the requesting app.
1616 * Always non-null for a {@link #REQUEST_TYPE_SHORTCUT} request, and always null for a
1617 * different request type.
1618 *
1619 * @return requested {@link ShortcutInfo} when a request is of the
1620 * {@link #REQUEST_TYPE_SHORTCUT} type. Null otherwise.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001621 */
1622 @Nullable
1623 public ShortcutInfo getShortcutInfo() {
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001624 try {
1625 return mInner.getShortcutInfo();
1626 } catch (RemoteException e) {
1627 throw e.rethrowAsRuntimeException();
1628 }
Makoto Onuki2d895c32016-12-02 15:48:40 -08001629 }
1630
1631 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001632 * {@link AppWidgetProviderInfo} sent by the requesting app.
1633 * Always non-null for a {@link #REQUEST_TYPE_APPWIDGET} request, and always null for a
1634 * different request type.
1635 *
Sunny Goyale7712ad2018-03-08 11:23:06 -08001636 * <p>Launcher should not show any configuration activity associated with the provider, and
1637 * assume that the widget is already fully configured. Upon accepting the widget, it should
1638 * pass the widgetId in {@link #accept(Bundle)}.
1639 *
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001640 * @return requested {@link AppWidgetProviderInfo} when a request is of the
1641 * {@link #REQUEST_TYPE_APPWIDGET} type. Null otherwise.
Sunny Goyal87a563e2017-01-01 19:42:45 -08001642 */
1643 @Nullable
Sunny Goyal970d4b42017-01-19 15:07:36 -08001644 public AppWidgetProviderInfo getAppWidgetProviderInfo(Context context) {
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001645 try {
1646 final AppWidgetProviderInfo info = mInner.getAppWidgetProviderInfo();
1647 if (info == null) {
1648 return null;
1649 }
Sunny Goyal970d4b42017-01-19 15:07:36 -08001650 info.updateDimensions(context.getResources().getDisplayMetrics());
1651 return info;
Makoto Onuki8abba3a2017-02-24 11:34:54 -08001652 } catch (RemoteException e) {
1653 throw e.rethrowAsRuntimeException();
Sunny Goyal970d4b42017-01-19 15:07:36 -08001654 }
Sunny Goyal87a563e2017-01-01 19:42:45 -08001655 }
1656
1657 /**
Sunny Goyal4ad6b572017-02-28 11:11:51 -08001658 * Any extras sent by the requesting app.
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001659 *
1660 * @return For a shortcut request, this method always return null. For an AppWidget
1661 * request, this method returns the extras passed to the
1662 * {@link android.appwidget.AppWidgetManager#requestPinAppWidget(
1663 * ComponentName, Bundle, PendingIntent)} API. See {@link AppWidgetManager} for details.
Sunny Goyal4ad6b572017-02-28 11:11:51 -08001664 */
1665 @Nullable
1666 public Bundle getExtras() {
1667 try {
1668 return mInner.getExtras();
1669 } catch (RemoteException e) {
1670 throw e.rethrowAsRuntimeException();
1671 }
1672 }
1673
1674 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001675 * Return whether a request is still valid.
1676 *
1677 * @return {@code TRUE} if a request is valid and {@link #accept(Bundle)} may be called.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001678 */
1679 public boolean isValid() {
1680 try {
1681 return mInner.isValid();
1682 } catch (RemoteException e) {
1683 return false;
1684 }
1685 }
1686
1687 /**
1688 * Called by the receiving launcher app when the user accepts the request.
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001689 *
1690 * @param options must be set for a {@link #REQUEST_TYPE_APPWIDGET} request.
1691 *
1692 * @return {@code TRUE} if the shortcut or the AppWidget has actually been pinned.
1693 * {@code FALSE} if the item hasn't been pinned, for example, because the request had
1694 * already been canceled, in which case the launcher must not pin the requested item.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001695 */
1696 public boolean accept(@Nullable Bundle options) {
1697 try {
1698 return mInner.accept(options);
1699 } catch (RemoteException e) {
1700 throw e.rethrowFromSystemServer();
1701 }
1702 }
1703
1704 /**
Makoto Onukia37ac3d2017-04-14 12:33:10 -07001705 * Called by the receiving launcher app when the user accepts the request, with no options.
1706 *
1707 * @return {@code TRUE} if the shortcut or the AppWidget has actually been pinned.
1708 * {@code FALSE} if the item hasn't been pinned, for example, because the request had
1709 * already been canceled, in which case the launcher must not pin the requested item.
Makoto Onuki2d895c32016-12-02 15:48:40 -08001710 */
1711 public boolean accept() {
1712 return accept(/* options= */ null);
1713 }
1714
1715 private PinItemRequest(Parcel source) {
1716 final ClassLoader cl = getClass().getClassLoader();
1717
1718 mRequestType = source.readInt();
Makoto Onuki2d895c32016-12-02 15:48:40 -08001719 mInner = IPinItemRequest.Stub.asInterface(source.readStrongBinder());
1720 }
1721
1722 @Override
1723 public void writeToParcel(Parcel dest, int flags) {
1724 dest.writeInt(mRequestType);
Makoto Onuki2d895c32016-12-02 15:48:40 -08001725 dest.writeStrongBinder(mInner.asBinder());
1726 }
1727
1728 public static final Creator<PinItemRequest> CREATOR =
1729 new Creator<PinItemRequest>() {
1730 public PinItemRequest createFromParcel(Parcel source) {
1731 return new PinItemRequest(source);
1732 }
1733 public PinItemRequest[] newArray(int size) {
1734 return new PinItemRequest[size];
1735 }
1736 };
1737
1738 @Override
1739 public int describeContents() {
1740 return 0;
1741 }
1742 }
Varun Shah2546cef2019-01-11 15:50:54 -08001743
1744 /**
1745 * A class that encapsulates information about the usage limit set for an app or
1746 * a group of apps.
1747 *
Varun Shah9c6f72b2019-01-25 21:13:56 -08001748 * <p>The launcher can query specifics about the usage limit such as how much usage time
1749 * the limit has and how much of the total usage time is remaining via the APIs available
1750 * in this class.
Varun Shah2546cef2019-01-11 15:50:54 -08001751 *
1752 * @see #getAppUsageLimit(String, UserHandle)
1753 */
1754 public static final class AppUsageLimit implements Parcelable {
Varun Shah2546cef2019-01-11 15:50:54 -08001755 private final long mTotalUsageLimit;
1756 private final long mUsageRemaining;
1757
1758 /** @hide */
Varun Shah9c6f72b2019-01-25 21:13:56 -08001759 public AppUsageLimit(long totalUsageLimit, long usageRemaining) {
Varun Shah2546cef2019-01-11 15:50:54 -08001760 this.mTotalUsageLimit = totalUsageLimit;
1761 this.mUsageRemaining = usageRemaining;
1762 }
1763
1764 /**
Varun Shah2546cef2019-01-11 15:50:54 -08001765 * Returns the total usage limit in milliseconds set for an app or a group of apps.
1766 *
1767 * @return the total usage limit in milliseconds
1768 */
1769 public long getTotalUsageLimit() {
1770 return mTotalUsageLimit;
1771 }
1772
1773 /**
1774 * Returns the usage remaining in milliseconds for an app or the group of apps
1775 * this limit refers to.
1776 *
1777 * @return the usage remaining in milliseconds
1778 */
1779 public long getUsageRemaining() {
1780 return mUsageRemaining;
1781 }
1782
1783 private AppUsageLimit(Parcel source) {
Varun Shah2546cef2019-01-11 15:50:54 -08001784 mTotalUsageLimit = source.readLong();
1785 mUsageRemaining = source.readLong();
1786 }
1787
1788 public static final Creator<AppUsageLimit> CREATOR = new Creator<AppUsageLimit>() {
1789 @Override
1790 public AppUsageLimit createFromParcel(Parcel source) {
1791 return new AppUsageLimit(source);
1792 }
1793
1794 @Override
1795 public AppUsageLimit[] newArray(int size) {
1796 return new AppUsageLimit[size];
1797 }
1798 };
1799
1800 @Override
1801 public int describeContents() {
1802 return 0;
1803 }
1804
1805 @Override
1806 public void writeToParcel(Parcel dest, int flags) {
Varun Shah2546cef2019-01-11 15:50:54 -08001807 dest.writeLong(mTotalUsageLimit);
1808 dest.writeLong(mUsageRemaining);
1809 }
1810 }
Amith Yamasani4f582632014-02-19 14:31:52 -08001811}