/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.content.pm;

import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageInstaller.SessionCallback;
import android.content.pm.PackageInstaller.SessionCallbackDelegate;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.DisplayMetrics;
import android.util.Log;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;

/**
 * Class for retrieving a list of launchable activities for the current user and any associated
 * managed profiles that are visible to the current user, which can be retrieved with
 * {@link #getProfiles}. This is mainly for use by launchers.
 *
 * Apps can be queried for each user profile.
 * Since the PackageManager will not deliver package broadcasts for other profiles, you can register
 * for package changes here.
 * <p>
 * To watch for managed profiles being added or removed, register for the following broadcasts:
 * {@link Intent#ACTION_MANAGED_PROFILE_ADDED} and {@link Intent#ACTION_MANAGED_PROFILE_REMOVED}.
 * <p>
 * Note as of Android O, apps on a managed profile are no longer allowed to access apps on the
 * main profile.  Apps can only access profiles returned by {@link #getProfiles()}.
 */
@SystemService(Context.LAUNCHER_APPS_SERVICE)
public class LauncherApps {

    static final String TAG = "LauncherApps";
    static final boolean DEBUG = false;

    /**
     * Activity Action: For the default launcher to show the confirmation dialog to create
     * a pinned shortcut.
     *
     * <p>See the {@link ShortcutManager} javadoc for details.
     *
     * <p>
     * Use {@link #getPinItemRequest(Intent)} to get a {@link PinItemRequest} object,
     * and call {@link PinItemRequest#accept(Bundle)}
     * if the user accepts.  If the user doesn't accept, no further action is required.
     *
     * @see #EXTRA_PIN_ITEM_REQUEST
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_CONFIRM_PIN_SHORTCUT =
            "android.content.pm.action.CONFIRM_PIN_SHORTCUT";

    /**
     * Activity Action: For the default launcher to show the confirmation dialog to create
     * a pinned app widget.
     *
     * <p>See the {@link android.appwidget.AppWidgetManager#requestPinAppWidget} javadoc for
     * details.
     *
     * <p>
     * Use {@link #getPinItemRequest(Intent)} to get a {@link PinItemRequest} object,
     * and call {@link PinItemRequest#accept(Bundle)}
     * if the user accepts.  If the user doesn't accept, no further action is required.
     *
     * @see #EXTRA_PIN_ITEM_REQUEST
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_CONFIRM_PIN_APPWIDGET =
            "android.content.pm.action.CONFIRM_PIN_APPWIDGET";

    /**
     * An extra for {@link #ACTION_CONFIRM_PIN_SHORTCUT} &amp; {@link #ACTION_CONFIRM_PIN_APPWIDGET}
     * containing a {@link PinItemRequest} of appropriate type asked to pin.
     *
     * <p>A helper function {@link #getPinItemRequest(Intent)} can be used
     * instead of using this constant directly.
     *
     * @see #ACTION_CONFIRM_PIN_SHORTCUT
     * @see #ACTION_CONFIRM_PIN_APPWIDGET
     */
    public static final String EXTRA_PIN_ITEM_REQUEST =
            "android.content.pm.extra.PIN_ITEM_REQUEST";

    private final Context mContext;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private final ILauncherApps mService;
    @UnsupportedAppUsage
    private final PackageManager mPm;
    private final UserManager mUserManager;

    private final List<CallbackMessageHandler> mCallbacks = new ArrayList<>();
    private final List<SessionCallbackDelegate> mDelegates = new ArrayList<>();

    /**
     * Callbacks for package changes to this and related managed profiles.
     */
    public static abstract class Callback {
        /**
         * Indicates that a package was removed from the specified profile.
         *
         * If a package is removed while being updated onPackageChanged will be
         * called instead.
         *
         * @param packageName The name of the package that was removed.
         * @param user The UserHandle of the profile that generated the change.
         */
        abstract public void onPackageRemoved(String packageName, UserHandle user);

        /**
         * Indicates that a package was added to the specified profile.
         *
         * If a package is added while being updated then onPackageChanged will be
         * called instead.
         *
         * @param packageName The name of the package that was added.
         * @param user The UserHandle of the profile that generated the change.
         */
        abstract public void onPackageAdded(String packageName, UserHandle user);

        /**
         * Indicates that a package was modified in the specified profile.
         * This can happen, for example, when the package is updated or when
         * one or more components are enabled or disabled.
         *
         * @param packageName The name of the package that has changed.
         * @param user The UserHandle of the profile that generated the change.
         */
        abstract public void onPackageChanged(String packageName, UserHandle user);

        /**
         * Indicates that one or more packages have become available. For
         * example, this can happen when a removable storage card has
         * reappeared.
         *
         * @param packageNames The names of the packages that have become
         *            available.
         * @param user The UserHandle of the profile that generated the change.
         * @param replacing Indicates whether these packages are replacing
         *            existing ones.
         */
        abstract public void onPackagesAvailable(String[] packageNames, UserHandle user,
                boolean replacing);

        /**
         * Indicates that one or more packages have become unavailable. For
         * example, this can happen when a removable storage card has been
         * removed.
         *
         * @param packageNames The names of the packages that have become
         *            unavailable.
         * @param user The UserHandle of the profile that generated the change.
         * @param replacing Indicates whether the packages are about to be
         *            replaced with new versions.
         */
        abstract public void onPackagesUnavailable(String[] packageNames, UserHandle user,
                boolean replacing);

        /**
         * Indicates that one or more packages have been suspended. For
         * example, this can happen when a Device Administrator suspends
         * an applicaton.
         *
         * <p>Note: On devices running {@link android.os.Build.VERSION_CODES#P Android P} or higher,
         * any apps that override {@link #onPackagesSuspended(String[], UserHandle, Bundle)} will
         * not receive this callback.
         *
         * @param packageNames The names of the packages that have just been
         *            suspended.
         * @param user The UserHandle of the profile that generated the change.
         */
        public void onPackagesSuspended(String[] packageNames, UserHandle user) {
        }

        /**
         * Indicates that one or more packages have been suspended. A device administrator or an app
         * with {@code android.permission.SUSPEND_APPS} can do this.
         *
         * <p>A suspending app with the permission {@code android.permission.SUSPEND_APPS} can
         * optionally provide a {@link Bundle} of extra information that it deems helpful for the
         * launcher to handle the suspended state of these packages. The contents of this
         * {@link Bundle} are supposed to be a contract between the suspending app and the launcher.
         *
         * @param packageNames The names of the packages that have just been suspended.
         * @param user the user for which the given packages were suspended.
         * @param launcherExtras A {@link Bundle} of extras for the launcher, if provided to the
         *                      system, {@code null} otherwise.
         * @see PackageManager#isPackageSuspended()
         * @see #getSuspendedPackageLauncherExtras(String, UserHandle)
         * @deprecated {@code launcherExtras} should be obtained by using
         * {@link #getSuspendedPackageLauncherExtras(String, UserHandle)}. For all other cases,
         * {@link #onPackagesSuspended(String[], UserHandle)} should be used.
         */
        @Deprecated
        public void onPackagesSuspended(String[] packageNames, UserHandle user,
                @Nullable Bundle launcherExtras) {
            onPackagesSuspended(packageNames, user);
        }

        /**
         * Indicates that one or more packages have been unsuspended. For
         * example, this can happen when a Device Administrator unsuspends
         * an applicaton.
         *
         * @param packageNames The names of the packages that have just been
         *            unsuspended.
         * @param user The UserHandle of the profile that generated the change.
         */
        public void onPackagesUnsuspended(String[] packageNames, UserHandle user) {
        }

        /**
         * Indicates that one or more shortcuts of any kind (dynamic, pinned, or manifest)
         * have been added, updated or removed.
         *
         * <p>Only the applications that are allowed to access the shortcut information,
         * as defined in {@link #hasShortcutHostPermission()}, will receive it.
         *
         * @param packageName The name of the package that has the shortcuts.
         * @param shortcuts All shortcuts from the package (dynamic, manifest and/or pinned).
         *    Only "key" information will be provided, as defined in
         *    {@link ShortcutInfo#hasKeyFieldsOnly()}.
         * @param user The UserHandle of the profile that generated the change.
         *
         * @see ShortcutManager
         */
        public void onShortcutsChanged(@NonNull String packageName,
                @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
        }
    }

    /**
     * Represents a query passed to {@link #getShortcuts(ShortcutQuery, UserHandle)}.
     */
    public static class ShortcutQuery {
        /**
         * Include dynamic shortcuts in the result.
         */
        public static final int FLAG_MATCH_DYNAMIC = 1 << 0;

        /** @hide kept for unit tests */
        @Deprecated
        public static final int FLAG_GET_DYNAMIC = FLAG_MATCH_DYNAMIC;

        /**
         * Include pinned shortcuts in the result.
         *
         * <p>If you are the selected assistant app, and wishes to fetch all shortcuts that the
         * user owns on the launcher (or by other launchers, in case the user has multiple), use
         * {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} instead.
         *
         * <p>If you're a regular launcher app, there's no way to get shortcuts pinned by other
         * launchers, and {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} will be ignored. So use this
         * flag to get own pinned shortcuts.
         */
        public static final int FLAG_MATCH_PINNED = 1 << 1;

        /** @hide kept for unit tests */
        @Deprecated
        public static final int FLAG_GET_PINNED = FLAG_MATCH_PINNED;

        /**
         * Include manifest shortcuts in the result.
         */
        public static final int FLAG_MATCH_MANIFEST = 1 << 3;

        /** @hide kept for unit tests */
        @Deprecated
        public static final int FLAG_GET_MANIFEST = FLAG_MATCH_MANIFEST;

        /**
         * Include all pinned shortcuts by any launchers, not just by the caller,
         * in the result.
         *
         * <p>The caller must be the selected assistant app to use this flag, or have the system
         * {@code ACCESS_SHORTCUTS} permission.
         *
         * <p>If you are the selected assistant app, and wishes to fetch all shortcuts that the
         * user owns on the launcher (or by other launchers, in case the user has multiple), use
         * {@link #FLAG_MATCH_PINNED_BY_ANY_LAUNCHER} instead.
         *
         * <p>If you're a regular launcher app (or any app that's not the selected assistant app)
         * then this flag will be ignored.
         */
        public static final int FLAG_MATCH_PINNED_BY_ANY_LAUNCHER = 1 << 10;

        /**
         * FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST
         * @hide
         */
        public static final int FLAG_MATCH_ALL_KINDS =
                FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST;

        /**
         * FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED | FLAG_MATCH_MANIFEST | FLAG_MATCH_ALL_PINNED
         * @hide
         */
        public static final int FLAG_MATCH_ALL_KINDS_WITH_ALL_PINNED =
                FLAG_MATCH_ALL_KINDS | FLAG_MATCH_PINNED_BY_ANY_LAUNCHER;

        /** @hide kept for unit tests */
        @Deprecated
        public static final int FLAG_GET_ALL_KINDS = FLAG_MATCH_ALL_KINDS;

        /**
         * Requests "key" fields only.  See {@link ShortcutInfo#hasKeyFieldsOnly()}'s javadoc to
         * see which fields fields "key".
         * This allows quicker access to shortcut information in order to
         * determine whether the caller's in-memory cache needs to be updated.
         *
         * <p>Typically, launcher applications cache all or most shortcut information
         * in memory in order to show shortcuts without a delay.
         *
         * When a given launcher application wants to update its cache, such as when its process
         * restarts, it can fetch shortcut information with this flag.
         * The application can then check {@link ShortcutInfo#getLastChangedTimestamp()} for each
         * shortcut, fetching a shortcut's non-key information only if that shortcut has been
         * updated.
         *
         * @see ShortcutManager
         */
        public static final int FLAG_GET_KEY_FIELDS_ONLY = 1 << 2;

        /** @hide */
        @IntDef(flag = true, prefix = { "FLAG_" }, value = {
                FLAG_MATCH_DYNAMIC,
                FLAG_MATCH_PINNED,
                FLAG_MATCH_MANIFEST,
                FLAG_GET_KEY_FIELDS_ONLY,
                FLAG_MATCH_MANIFEST,
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface QueryFlags {}

        long mChangedSince;

        @Nullable
        String mPackage;

        @Nullable
        List<String> mShortcutIds;

        @Nullable
        ComponentName mActivity;

        @QueryFlags
        int mQueryFlags;

        public ShortcutQuery() {
        }

        /**
         * If non-zero, returns only shortcuts that have been added or updated
         * since the given timestamp, expressed in milliseconds since the Epoch&mdash;see
         * {@link System#currentTimeMillis()}.
         */
        public ShortcutQuery setChangedSince(long changedSince) {
            mChangedSince = changedSince;
            return this;
        }

        /**
         * If non-null, returns only shortcuts from the package.
         */
        public ShortcutQuery setPackage(@Nullable String packageName) {
            mPackage = packageName;
            return this;
        }

        /**
         * If non-null, return only the specified shortcuts by ID.  When setting this field,
         * a package name must also be set with {@link #setPackage}.
         */
        public ShortcutQuery setShortcutIds(@Nullable List<String> shortcutIds) {
            mShortcutIds = shortcutIds;
            return this;
        }

        /**
         * If non-null, returns only shortcuts associated with the activity; i.e.
         * {@link ShortcutInfo}s whose {@link ShortcutInfo#getActivity()} are equal
         * to {@code activity}.
         */
        public ShortcutQuery setActivity(@Nullable ComponentName activity) {
            mActivity = activity;
            return this;
        }

        /**
         * Set query options.  At least one of the {@code MATCH} flags should be set.  Otherwise,
         * no shortcuts will be returned.
         *
         * <ul>
         *     <li>{@link #FLAG_MATCH_DYNAMIC}
         *     <li>{@link #FLAG_MATCH_PINNED}
         *     <li>{@link #FLAG_MATCH_MANIFEST}
         *     <li>{@link #FLAG_GET_KEY_FIELDS_ONLY}
         * </ul>
         */
        public ShortcutQuery setQueryFlags(@QueryFlags int queryFlags) {
            mQueryFlags = queryFlags;
            return this;
        }
    }

    /** @hide */
    public LauncherApps(Context context, ILauncherApps service) {
        mContext = context;
        mService = service;
        mPm = context.getPackageManager();
        mUserManager = context.getSystemService(UserManager.class);
    }

    /** @hide */
    @TestApi
    public LauncherApps(Context context) {
        this(context, ILauncherApps.Stub.asInterface(
                ServiceManager.getService(Context.LAUNCHER_APPS_SERVICE)));
    }

    /**
     * Show an error log on logcat, when the calling user is a managed profile, and the target
     * user is different from the calling user, in order to help developers to detect it.
     */
    private void logErrorForInvalidProfileAccess(@NonNull UserHandle target) {
        if (UserHandle.myUserId() != target.getIdentifier() && mUserManager.isManagedProfile()) {
            Log.w(TAG, "Accessing other profiles/users from managed profile is no longer allowed.");
        }
    }

    /**
     * Return a list of profiles that the caller can access via the {@link LauncherApps} APIs.
     *
     * <p>If the caller is running on a managed profile, it'll return only the current profile.
     * Otherwise it'll return the same list as {@link UserManager#getUserProfiles()} would.
     */
    public List<UserHandle> getProfiles() {
        if (mUserManager.isManagedProfile()) {
            // If it's a managed profile, only return the current profile.
            final List result =  new ArrayList(1);
            result.add(android.os.Process.myUserHandle());
            return result;
        } else {
            return mUserManager.getUserProfiles();
        }
    }

    /**
     * Retrieves a list of activities that specify {@link Intent#ACTION_MAIN} and
     * {@link Intent#CATEGORY_LAUNCHER}, across all apps, for a specified user. If an app doesn't
     * have any activities that specify <code>ACTION_MAIN</code> or <code>CATEGORY_LAUNCHER</code>,
     * the system adds a synthesized activity to the list. This synthesized activity represents the
     * app's details page within system settings.
     *
     * <p class="note"><b>Note: </b>It's possible for system apps, such as app stores, to prevent
     * the system from adding synthesized activities to the returned list.</p>
     *
     * <p>As of <a href="/reference/android/os/Build.VERSION_CODES.html#Q">Android Q</a>, at least
     * one of the app's activities or synthesized activities appears in the returned list unless the
     * app satisfies at least one of the following conditions:</p>
     * <ul>
     * <li>The app is a system app.</li>
     * <li>The app doesn't request any <a href="/guide/topics/permissions/overview">permissions</a>.
     * </li>
     * <li>The app doesn't have a <em>launcher activity</em> that is enabled by default. A launcher
     * activity has an intent containing the <code>ACTION_MAIN</code> action and the
     * <code>CATEGORY_LAUNCHER</code> category.</li>
     * </ul>
     *
     * <p>Additionally, the system hides synthesized activities for some or all apps in the
     * following enterprise-related cases:</p>
     * <ul>
     * <li>If the device is a
     * <a href="https://developers.google.com/android/work/overview#company-owned-devices-for-knowledge-workers">fully
     * managed device</a>, no synthesized activities for any app appear in the returned list.</li>
     * <li>If the current user has a
     * <a href="https://developers.google.com/android/work/overview#employee-owned-devices-byod">work
     * profile</a>, no synthesized activities for the user's work apps appear in the returned
     * list.</li>
     * </ul>
     *
     * @param packageName The specific package to query. If null, it checks all installed packages
     *            in the profile.
     * @param user The UserHandle of the profile.
     * @return List of launchable activities. Can be an empty list but will not be null.
     */
    public List<LauncherActivityInfo> getActivityList(String packageName, UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        try {
            return convertToActivityList(mService.getLauncherActivities(mContext.getPackageName(),
                    packageName, user), user);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Returns the activity info for a given intent and user handle, if it resolves. Otherwise it
     * returns null.
     *
     * @param intent The intent to find a match for.
     * @param user The profile to look in for a match.
     * @return An activity info object if there is a match.
     */
    public LauncherActivityInfo resolveActivity(Intent intent, UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        try {
            ActivityInfo ai = mService.resolveActivity(mContext.getPackageName(),
                    intent.getComponent(), user);
            if (ai != null) {
                LauncherActivityInfo info = new LauncherActivityInfo(mContext, ai, user);
                return info;
            }
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
        return null;
    }

    /**
     * Starts a Main activity in the specified profile.
     *
     * @param component The ComponentName of the activity to launch
     * @param user The UserHandle of the profile
     * @param sourceBounds The Rect containing the source bounds of the clicked icon
     * @param opts Options to pass to startActivity
     */
    public void startMainActivity(ComponentName component, UserHandle user, Rect sourceBounds,
            Bundle opts) {
        logErrorForInvalidProfileAccess(user);
        if (DEBUG) {
            Log.i(TAG, "StartMainActivity " + component + " " + user.getIdentifier());
        }
        try {
            mService.startActivityAsUser(mContext.getIApplicationThread(),
                    mContext.getPackageName(),
                    component, sourceBounds, opts, user);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Starts an activity to show the details of the specified session.
     *
     * @param sessionInfo The SessionInfo of the session
     * @param sourceBounds The Rect containing the source bounds of the clicked icon
     * @param opts Options to pass to startActivity
     */
    public void startPackageInstallerSessionDetailsActivity(@NonNull SessionInfo sessionInfo,
            @Nullable Rect sourceBounds, @Nullable Bundle opts) {
        try {
            mService.startSessionDetailsActivityAsUser(mContext.getIApplicationThread(),
                    mContext.getPackageName(), sessionInfo, sourceBounds, opts,
                    sessionInfo.getUser());
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Starts the settings activity to show the application details for a
     * package in the specified profile.
     *
     * @param component The ComponentName of the package to launch settings for.
     * @param user The UserHandle of the profile
     * @param sourceBounds The Rect containing the source bounds of the clicked icon
     * @param opts Options to pass to startActivity
     */
    public void startAppDetailsActivity(ComponentName component, UserHandle user,
            Rect sourceBounds, Bundle opts) {
        logErrorForInvalidProfileAccess(user);
        try {
            mService.showAppDetailsAsUser(mContext.getIApplicationThread(),
                    mContext.getPackageName(),
                    component, sourceBounds, opts, user);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Retrieves a list of config activities for creating {@link ShortcutInfo}.
     *
     * @param packageName The specific package to query. If null, it checks all installed packages
     *            in the profile.
     * @param user The UserHandle of the profile.
     * @return List of config activities. Can be an empty list but will not be null.
     *
     * @see Intent#ACTION_CREATE_SHORTCUT
     * @see #getShortcutConfigActivityIntent(LauncherActivityInfo)
     */
    public List<LauncherActivityInfo> getShortcutConfigActivityList(@Nullable String packageName,
            @NonNull UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        try {
            return convertToActivityList(mService.getShortcutConfigActivities(
                    mContext.getPackageName(), packageName, user),
                    user);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    private List<LauncherActivityInfo> convertToActivityList(
            @Nullable ParceledListSlice<ResolveInfo> activities, UserHandle user) {
        if (activities == null) {
            return Collections.EMPTY_LIST;
        }
        ArrayList<LauncherActivityInfo> lais = new ArrayList<>();
        for (ResolveInfo ri : activities.getList()) {
            LauncherActivityInfo lai = new LauncherActivityInfo(mContext, ri.activityInfo, user);
            if (DEBUG) {
                Log.v(TAG, "Returning activity for profile " + user + " : "
                        + lai.getComponentName());
            }
            lais.add(lai);
        }
        return lais;
    }

    /**
     * Returns an intent sender which can be used to start the configure activity for creating
     * custom shortcuts. Use this method if the provider is in another profile as you are not
     * allowed to start an activity in another profile.
     *
     * <p>The caller should receive {@link PinItemRequest} in onActivityResult on
     * {@link android.app.Activity#RESULT_OK}.
     *
     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
     * #hasShortcutHostPermission()}.
     *
     * @param info a configuration activity returned by {@link #getShortcutConfigActivityList}
     *
     * @throws IllegalStateException when the user is locked or not running.
     * @throws SecurityException if {@link #hasShortcutHostPermission()} is false.
     *
     * @see #getPinItemRequest(Intent)
     * @see Intent#ACTION_CREATE_SHORTCUT
     * @see android.app.Activity#startIntentSenderForResult
     */
    @Nullable
    public IntentSender getShortcutConfigActivityIntent(@NonNull LauncherActivityInfo info) {
        try {
            return mService.getShortcutConfigActivityIntent(
                    mContext.getPackageName(), info.getComponentName(), info.getUser());
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Checks if the package is installed and enabled for a profile.
     *
     * @param packageName The package to check.
     * @param user The UserHandle of the profile.
     *
     * @return true if the package exists and is enabled.
     */
    public boolean isPackageEnabled(String packageName, UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        try {
            return mService.isPackageEnabled(mContext.getPackageName(), packageName, user);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Gets the launcher extras supplied to the system when the given package was suspended via
     * {@code PackageManager#setPackagesSuspended(String[], boolean, PersistableBundle,
     * PersistableBundle, String)}.
     *
     * <p>The contents of this {@link Bundle} are supposed to be a contract between the suspending
     * app and the launcher.
     *
     * <p>Note: This just returns whatever extras were provided to the system, <em>which might
     * even be {@code null}.</em>
     *
     * @param packageName The package for which to fetch the launcher extras.
     * @param user The {@link UserHandle} of the profile.
     * @return A {@link Bundle} of launcher extras. Or {@code null} if the package is not currently
     *         suspended.
     *
     * @see Callback#onPackagesSuspended(String[], UserHandle, Bundle)
     * @see PackageManager#isPackageSuspended()
     */
    public @Nullable Bundle getSuspendedPackageLauncherExtras(String packageName, UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        try {
            return mService.getSuspendedPackageLauncherExtras(packageName, user);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Returns whether a package should be hidden from suggestions to the user. Currently, this
     * could be done because the package was marked as distracting to the user via
     * {@code PackageManager.setDistractingPackageRestrictions(String[], int)}.
     *
     * @param packageName The package for which to check.
     * @param user the {@link UserHandle} of the profile.
     * @return
     */
    public boolean shouldHideFromSuggestions(@NonNull String packageName,
            @NonNull UserHandle user) {
        Objects.requireNonNull(packageName, "packageName");
        Objects.requireNonNull(user, "user");
        try {
            return mService.shouldHideFromSuggestions(packageName, user);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Returns {@link ApplicationInfo} about an application installed for a specific user profile.
     *
     * @param packageName The package name of the application
     * @param flags Additional option flags {@link PackageManager#getApplicationInfo}
     * @param user The UserHandle of the profile.
     *
     * @return {@link ApplicationInfo} containing information about the package. Returns
     *         {@code null} if the package isn't installed for the given profile, or the profile
     *         isn't enabled.
     */
    public ApplicationInfo getApplicationInfo(@NonNull String packageName,
            @ApplicationInfoFlags int flags, @NonNull UserHandle user)
            throws PackageManager.NameNotFoundException {
        Objects.requireNonNull(packageName, "packageName");
        Objects.requireNonNull(user, "user");
        logErrorForInvalidProfileAccess(user);
        try {
            final ApplicationInfo ai = mService
                    .getApplicationInfo(mContext.getPackageName(), packageName, flags, user);
            if (ai == null) {
                throw new NameNotFoundException("Package " + packageName + " not found for user "
                        + user.getIdentifier());
            }
            return ai;
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Returns an object describing the app usage limit for the given package.
     * If there are multiple limits that apply to the package, the one with the smallest
     * time remaining will be returned.
     *
     * @param packageName name of the package whose app usage limit will be returned
     * @param user the user of the package
     *
     * @return an {@link AppUsageLimit} object describing the app time limit containing
     * the given package with the smallest time remaining, or {@code null} if none exist.
     * @throws SecurityException when the caller is not the recents app.
     * @hide
     */
    @Nullable
    @SystemApi
    public LauncherApps.AppUsageLimit getAppUsageLimit(@NonNull String packageName,
            @NonNull UserHandle user) {
        try {
            return mService.getAppUsageLimit(mContext.getPackageName(), packageName, user);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Checks if the activity exists and it enabled for a profile.
     *
     * <p>The activity may still not be exported, in which case {@link #startMainActivity} will
     * throw a {@link SecurityException} unless the caller has the same UID as the target app's.
     *
     * @param component The activity to check.
     * @param user The UserHandle of the profile.
     *
     * @return true if the activity exists and is enabled.
     */
    public boolean isActivityEnabled(ComponentName component, UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        try {
            return mService.isActivityEnabled(mContext.getPackageName(), component, user);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    /**
     * Returns whether the caller can access the shortcut information.  Access is currently
     * available to:
     *
     * <ul>
     *     <li>The current launcher (or default launcher if there is no set current launcher).</li>
     *     <li>The currently active voice interaction service.</li>
     * </ul>
     *
     * <p>Note when this method returns {@code false}, it may be a temporary situation because
     * the user is trying a new launcher application.  The user may decide to change the default
     * launcher back to the calling application again, so even if a launcher application loses
     * this permission, it does <b>not</b> have to purge pinned shortcut information.
     * If the calling launcher application contains pinned shortcuts, they will still work,
     * even though the caller no longer has the shortcut host permission.
     *
     * @throws IllegalStateException when the user is locked.
     *
     * @see ShortcutManager
     */
    public boolean hasShortcutHostPermission() {
        try {
            return mService.hasShortcutHostPermission(mContext.getPackageName());
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

    private List<ShortcutInfo> maybeUpdateDisabledMessage(List<ShortcutInfo> shortcuts) {
        if (shortcuts == null) {
            return null;
        }
        for (int i = shortcuts.size() - 1; i >= 0; i--) {
            final ShortcutInfo si = shortcuts.get(i);
            final String message = ShortcutInfo.getDisabledReasonForRestoreIssue(mContext,
                    si.getDisabledReason());
            if (message != null) {
                si.setDisabledMessage(message);
            }
        }
        return shortcuts;
    }

    /**
     * Returns {@link ShortcutInfo}s that match {@code query}.
     *
     * <p>Callers must be allowed to access the shortcut information, as defined in {@link
     * #hasShortcutHostPermission()}.
     *
     * @param query result includes shortcuts matching this query.
     * @param user The UserHandle of the profile.
     *
     * @return the IDs of {@link ShortcutInfo}s that match the query.
     * @throws IllegalStateException when the user is locked, or when the {@code user} user
     * is locked or not running.
     *
     * @see ShortcutManager
     */
    @Nullable
    public List<ShortcutInfo> getShortcuts(@NonNull ShortcutQuery query,
            @NonNull UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        try {
            // Note this is the only case we need to update the disabled message for shortcuts
            // that weren't restored.
            // The restore problem messages are only shown by the user, and publishers will never
            // see them. The only other API that the launcher gets shortcuts is the shortcut
            // changed callback, but that only returns shortcuts with the "key" information, so
            // that won't return disabled message.
            return maybeUpdateDisabledMessage(mService.getShortcuts(mContext.getPackageName(),
                    query.mChangedSince, query.mPackage, query.mShortcutIds, query.mActivity,
                    query.mQueryFlags, user)
                    .getList());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @hide // No longer used.  Use getShortcuts() instead.  Kept for unit tests.
     */
    @Nullable
    @Deprecated
    public List<ShortcutInfo> getShortcutInfo(@NonNull String packageName,
            @NonNull List<String> ids, @NonNull UserHandle user) {
        final ShortcutQuery q = new ShortcutQuery();
        q.setPackage(packageName);
        q.setShortcutIds(ids);
        q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
        return getShortcuts(q, user);
    }

    /**
     * Pin shortcuts on a package.
     *
     * <p>This API is <b>NOT</b> cumulative; this will replace all pinned shortcuts for the package.
     * However, different launchers may have different set of pinned shortcuts.
     *
     * <p>The calling launcher application must be allowed to access the shortcut information,
     * as defined in {@link #hasShortcutHostPermission()}.
     *
     * @param packageName The target package name.
     * @param shortcutIds The IDs of the shortcut to be pinned.
     * @param user The UserHandle of the profile.
     * @throws IllegalStateException when the user is locked, or when the {@code user} user
     * is locked or not running.
     *
     * @see ShortcutManager
     */
    public void pinShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
            @NonNull UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        try {
            mService.pinShortcuts(mContext.getPackageName(), packageName, shortcutIds, user);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * @hide kept for testing.
     */
    @Deprecated
    public int getShortcutIconResId(@NonNull ShortcutInfo shortcut) {
        return shortcut.getIconResourceId();
    }

    /**
     * @hide kept for testing.
     */
    @Deprecated
    public int getShortcutIconResId(@NonNull String packageName, @NonNull String shortcutId,
            @NonNull UserHandle user) {
        final ShortcutQuery q = new ShortcutQuery();
        q.setPackage(packageName);
        q.setShortcutIds(Arrays.asList(shortcutId));
        q.setQueryFlags(ShortcutQuery.FLAG_GET_ALL_KINDS);
        final List<ShortcutInfo> shortcuts = getShortcuts(q, user);

        return shortcuts.size() > 0 ? shortcuts.get(0).getIconResourceId() : 0;
    }

    /**
     * @hide internal/unit tests only
     */
    public ParcelFileDescriptor getShortcutIconFd(
            @NonNull ShortcutInfo shortcut) {
        return getShortcutIconFd(shortcut.getPackage(), shortcut.getId(),
                shortcut.getUserId());
    }

    /**
     * @hide internal/unit tests only
     */
    public ParcelFileDescriptor getShortcutIconFd(
            @NonNull String packageName, @NonNull String shortcutId, @NonNull UserHandle user) {
        return getShortcutIconFd(packageName, shortcutId, user.getIdentifier());
    }

    private ParcelFileDescriptor getShortcutIconFd(
            @NonNull String packageName, @NonNull String shortcutId, int userId) {
        try {
            return mService.getShortcutIconFd(mContext.getPackageName(),
                    packageName, shortcutId, userId);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Returns the icon for this shortcut, without any badging for the profile.
     *
     * <p>The calling launcher application must be allowed to access the shortcut information,
     * as defined in {@link #hasShortcutHostPermission()}.
     *
     * @param density The preferred density of the icon, zero for default density. Use
     * density DPI values from {@link DisplayMetrics}.
     *
     * @return The drawable associated with the shortcut.
     * @throws IllegalStateException when the user is locked, or when the {@code user} user
     * is locked or not running.
     *
     * @see ShortcutManager
     * @see #getShortcutBadgedIconDrawable(ShortcutInfo, int)
     * @see DisplayMetrics
     */
    public Drawable getShortcutIconDrawable(@NonNull ShortcutInfo shortcut, int density) {
        if (shortcut.hasIconFile()) {
            final ParcelFileDescriptor pfd = getShortcutIconFd(shortcut);
            if (pfd == null) {
                return null;
            }
            try {
                final Bitmap bmp = BitmapFactory.decodeFileDescriptor(pfd.getFileDescriptor());
                if (bmp != null) {
                    BitmapDrawable dr = new BitmapDrawable(mContext.getResources(), bmp);
                    if (shortcut.hasAdaptiveBitmap()) {
                        return new AdaptiveIconDrawable(null, dr);
                    } else {
                        return dr;
                    }
                }
                return null;
            } finally {
                try {
                    pfd.close();
                } catch (IOException ignore) {
                }
            }
        } else if (shortcut.hasIconResource()) {
            return loadDrawableResourceFromPackage(shortcut.getPackage(),
                    shortcut.getIconResourceId(), shortcut.getUserHandle(), density);
        } else if (shortcut.getIcon() != null) {
            // This happens if a shortcut is pending-approval.
            final Icon icon = shortcut.getIcon();
            switch (icon.getType()) {
                case Icon.TYPE_RESOURCE: {
                    return loadDrawableResourceFromPackage(shortcut.getPackage(),
                            icon.getResId(), shortcut.getUserHandle(), density);
                }
                case Icon.TYPE_BITMAP:
                case Icon.TYPE_ADAPTIVE_BITMAP: {
                    return icon.loadDrawable(mContext);
                }
                default:
                    return null; // Shouldn't happen though.
            }
        } else {
            return null; // Has no icon.
        }
    }

    private Drawable loadDrawableResourceFromPackage(String packageName, int resId,
            UserHandle user, int density) {
        try {
            if (resId == 0) {
                return null; // Shouldn't happen but just in case.
            }
            final ApplicationInfo ai = getApplicationInfo(packageName, /* flags =*/ 0, user);
            final Resources res = mContext.getPackageManager().getResourcesForApplication(ai);
            return res.getDrawableForDensity(resId, density);
        } catch (NameNotFoundException | Resources.NotFoundException e) {
            return null;
        }
    }

    /**
     * Returns the shortcut icon with badging appropriate for the profile.
     *
     * <p>The calling launcher application must be allowed to access the shortcut information,
     * as defined in {@link #hasShortcutHostPermission()}.
     *
     * @param density Optional density for the icon, or 0 to use the default density. Use
     * @return A badged icon for the shortcut.
     * @throws IllegalStateException when the user is locked, or when the {@code user} user
     * is locked or not running.
     *
     * @see ShortcutManager
     * @see #getShortcutIconDrawable(ShortcutInfo, int)
     * @see DisplayMetrics
     */
    public Drawable getShortcutBadgedIconDrawable(ShortcutInfo shortcut, int density) {
        final Drawable originalIcon = getShortcutIconDrawable(shortcut, density);

        return (originalIcon == null) ? null : mContext.getPackageManager().getUserBadgedIcon(
                originalIcon, shortcut.getUserHandle());
    }

    /**
     * Starts a shortcut.
     *
     * <p>The calling launcher application must be allowed to access the shortcut information,
     * as defined in {@link #hasShortcutHostPermission()}.
     *
     * @param packageName The target shortcut package name.
     * @param shortcutId The target shortcut ID.
     * @param sourceBounds The Rect containing the source bounds of the clicked icon.
     * @param startActivityOptions Options to pass to startActivity.
     * @param user The UserHandle of the profile.
     * @throws IllegalStateException when the user is locked, or when the {@code user} user
     * is locked or not running.
     *
     * @throws android.content.ActivityNotFoundException failed to start shortcut. (e.g.
     * the shortcut no longer exists, is disabled, the intent receiver activity doesn't exist, etc)
     */
    public void startShortcut(@NonNull String packageName, @NonNull String shortcutId,
            @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
            @NonNull UserHandle user) {
        logErrorForInvalidProfileAccess(user);

        startShortcut(packageName, shortcutId, sourceBounds, startActivityOptions,
                user.getIdentifier());
    }

    /**
     * Launches a shortcut.
     *
     * <p>The calling launcher application must be allowed to access the shortcut information,
     * as defined in {@link #hasShortcutHostPermission()}.
     *
     * @param shortcut The target shortcut.
     * @param sourceBounds The Rect containing the source bounds of the clicked icon.
     * @param startActivityOptions Options to pass to startActivity.
     * @throws IllegalStateException when the user is locked, or when the {@code user} user
     * is locked or not running.
     *
     * @throws android.content.ActivityNotFoundException failed to start shortcut. (e.g.
     * the shortcut no longer exists, is disabled, the intent receiver activity doesn't exist, etc)
     */
    public void startShortcut(@NonNull ShortcutInfo shortcut,
            @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions) {
        startShortcut(shortcut.getPackage(), shortcut.getId(),
                sourceBounds, startActivityOptions,
                shortcut.getUserId());
    }

    @UnsupportedAppUsage
    private void startShortcut(@NonNull String packageName, @NonNull String shortcutId,
            @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions,
            int userId) {
        try {
            final boolean success =
                    mService.startShortcut(mContext.getPackageName(), packageName, shortcutId,
                    sourceBounds, startActivityOptions, userId);
            if (!success) {
                throw new ActivityNotFoundException("Shortcut could not be started");
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Registers a callback for changes to packages in this user and managed profiles.
     *
     * @param callback The callback to register.
     */
    public void registerCallback(Callback callback) {
        registerCallback(callback, null);
    }

    /**
     * Registers a callback for changes to packages in this user and managed profiles.
     *
     * @param callback The callback to register.
     * @param handler that should be used to post callbacks on, may be null.
     */
    public void registerCallback(Callback callback, Handler handler) {
        synchronized (this) {
            if (callback != null && findCallbackLocked(callback) < 0) {
                boolean addedFirstCallback = mCallbacks.size() == 0;
                addCallbackLocked(callback, handler);
                if (addedFirstCallback) {
                    try {
                        mService.addOnAppsChangedListener(mContext.getPackageName(),
                                mAppsChangedListener);
                    } catch (RemoteException re) {
                        throw re.rethrowFromSystemServer();
                    }
                }
            }
        }
    }

    /**
     * Unregisters a callback that was previously registered.
     *
     * @param callback The callback to unregister.
     * @see #registerCallback(Callback)
     */
    public void unregisterCallback(Callback callback) {
        synchronized (this) {
            removeCallbackLocked(callback);
            if (mCallbacks.size() == 0) {
                try {
                    mService.removeOnAppsChangedListener(mAppsChangedListener);
                } catch (RemoteException re) {
                    throw re.rethrowFromSystemServer();
                }
            }
        }
    }

    /** @return position in mCallbacks for callback or -1 if not present. */
    private int findCallbackLocked(Callback callback) {
        if (callback == null) {
            throw new IllegalArgumentException("Callback cannot be null");
        }
        final int size = mCallbacks.size();
        for (int i = 0; i < size; ++i) {
            if (mCallbacks.get(i).mCallback == callback) {
                return i;
            }
        }
        return -1;
    }

    private void removeCallbackLocked(Callback callback) {
        int pos = findCallbackLocked(callback);
        if (pos >= 0) {
            mCallbacks.remove(pos);
        }
    }

    private void addCallbackLocked(Callback callback, Handler handler) {
        // Remove if already present.
        removeCallbackLocked(callback);
        if (handler == null) {
            handler = new Handler();
        }
        CallbackMessageHandler toAdd = new CallbackMessageHandler(handler.getLooper(), callback);
        mCallbacks.add(toAdd);
    }

    private IOnAppsChangedListener.Stub mAppsChangedListener = new IOnAppsChangedListener.Stub() {

        @Override
        public void onPackageRemoved(UserHandle user, String packageName)
                throws RemoteException {
            if (DEBUG) {
                Log.d(TAG, "onPackageRemoved " + user.getIdentifier() + "," + packageName);
            }
            synchronized (LauncherApps.this) {
                for (CallbackMessageHandler callback : mCallbacks) {
                    callback.postOnPackageRemoved(packageName, user);
                }
            }
        }

        @Override
        public void onPackageChanged(UserHandle user, String packageName) throws RemoteException {
            if (DEBUG) {
                Log.d(TAG, "onPackageChanged " + user.getIdentifier() + "," + packageName);
            }
            synchronized (LauncherApps.this) {
                for (CallbackMessageHandler callback : mCallbacks) {
                    callback.postOnPackageChanged(packageName, user);
                }
            }
        }

        @Override
        public void onPackageAdded(UserHandle user, String packageName) throws RemoteException {
            if (DEBUG) {
                Log.d(TAG, "onPackageAdded " + user.getIdentifier() + "," + packageName);
            }
            synchronized (LauncherApps.this) {
                for (CallbackMessageHandler callback : mCallbacks) {
                    callback.postOnPackageAdded(packageName, user);
                }
            }
        }

        @Override
        public void onPackagesAvailable(UserHandle user, String[] packageNames, boolean replacing)
                throws RemoteException {
            if (DEBUG) {
                Log.d(TAG, "onPackagesAvailable " + user.getIdentifier() + "," + packageNames);
            }
            synchronized (LauncherApps.this) {
                for (CallbackMessageHandler callback : mCallbacks) {
                    callback.postOnPackagesAvailable(packageNames, user, replacing);
                }
            }
        }

        @Override
        public void onPackagesUnavailable(UserHandle user, String[] packageNames, boolean replacing)
                throws RemoteException {
            if (DEBUG) {
                Log.d(TAG, "onPackagesUnavailable " + user.getIdentifier() + "," + packageNames);
            }
            synchronized (LauncherApps.this) {
                for (CallbackMessageHandler callback : mCallbacks) {
                    callback.postOnPackagesUnavailable(packageNames, user, replacing);
                }
            }
        }

        @Override
        public void onPackagesSuspended(UserHandle user, String[] packageNames,
                Bundle launcherExtras)
                throws RemoteException {
            if (DEBUG) {
                Log.d(TAG, "onPackagesSuspended " + user.getIdentifier() + "," + packageNames);
            }
            synchronized (LauncherApps.this) {
                for (CallbackMessageHandler callback : mCallbacks) {
                    callback.postOnPackagesSuspended(packageNames, launcherExtras, user);
                }
            }
        }

        @Override
        public void onPackagesUnsuspended(UserHandle user, String[] packageNames)
                throws RemoteException {
            if (DEBUG) {
                Log.d(TAG, "onPackagesUnsuspended " + user.getIdentifier() + "," + packageNames);
            }
            synchronized (LauncherApps.this) {
                for (CallbackMessageHandler callback : mCallbacks) {
                    callback.postOnPackagesUnsuspended(packageNames, user);
                }
            }
        }

        @Override
        public void onShortcutChanged(UserHandle user, String packageName,
                ParceledListSlice shortcuts) {
            if (DEBUG) {
                Log.d(TAG, "onShortcutChanged " + user.getIdentifier() + "," + packageName);
            }
            final List<ShortcutInfo> list = shortcuts.getList();
            synchronized (LauncherApps.this) {
                for (CallbackMessageHandler callback : mCallbacks) {
                    callback.postOnShortcutChanged(packageName, user, list);
                }
            }
        }
    };

    private static class CallbackMessageHandler extends Handler {
        private static final int MSG_ADDED = 1;
        private static final int MSG_REMOVED = 2;
        private static final int MSG_CHANGED = 3;
        private static final int MSG_AVAILABLE = 4;
        private static final int MSG_UNAVAILABLE = 5;
        private static final int MSG_SUSPENDED = 6;
        private static final int MSG_UNSUSPENDED = 7;
        private static final int MSG_SHORTCUT_CHANGED = 8;

        private LauncherApps.Callback mCallback;

        private static class CallbackInfo {
            String[] packageNames;
            String packageName;
            Bundle launcherExtras;
            boolean replacing;
            UserHandle user;
            List<ShortcutInfo> shortcuts;
        }

        public CallbackMessageHandler(Looper looper, LauncherApps.Callback callback) {
            super(looper, null, true);
            mCallback = callback;
        }

        @Override
        public void handleMessage(Message msg) {
            if (mCallback == null || !(msg.obj instanceof CallbackInfo)) {
                return;
            }
            CallbackInfo info = (CallbackInfo) msg.obj;
            switch (msg.what) {
                case MSG_ADDED:
                    mCallback.onPackageAdded(info.packageName, info.user);
                    break;
                case MSG_REMOVED:
                    mCallback.onPackageRemoved(info.packageName, info.user);
                    break;
                case MSG_CHANGED:
                    mCallback.onPackageChanged(info.packageName, info.user);
                    break;
                case MSG_AVAILABLE:
                    mCallback.onPackagesAvailable(info.packageNames, info.user, info.replacing);
                    break;
                case MSG_UNAVAILABLE:
                    mCallback.onPackagesUnavailable(info.packageNames, info.user, info.replacing);
                    break;
                case MSG_SUSPENDED:
                    mCallback.onPackagesSuspended(info.packageNames, info.user, info.launcherExtras
                    );
                    break;
                case MSG_UNSUSPENDED:
                    mCallback.onPackagesUnsuspended(info.packageNames, info.user);
                    break;
                case MSG_SHORTCUT_CHANGED:
                    mCallback.onShortcutsChanged(info.packageName, info.shortcuts, info.user);
                    break;
            }
        }

        public void postOnPackageAdded(String packageName, UserHandle user) {
            CallbackInfo info = new CallbackInfo();
            info.packageName = packageName;
            info.user = user;
            obtainMessage(MSG_ADDED, info).sendToTarget();
        }

        public void postOnPackageRemoved(String packageName, UserHandle user) {
            CallbackInfo info = new CallbackInfo();
            info.packageName = packageName;
            info.user = user;
            obtainMessage(MSG_REMOVED, info).sendToTarget();
        }

        public void postOnPackageChanged(String packageName, UserHandle user) {
            CallbackInfo info = new CallbackInfo();
            info.packageName = packageName;
            info.user = user;
            obtainMessage(MSG_CHANGED, info).sendToTarget();
        }

        public void postOnPackagesAvailable(String[] packageNames, UserHandle user,
                boolean replacing) {
            CallbackInfo info = new CallbackInfo();
            info.packageNames = packageNames;
            info.replacing = replacing;
            info.user = user;
            obtainMessage(MSG_AVAILABLE, info).sendToTarget();
        }

        public void postOnPackagesUnavailable(String[] packageNames, UserHandle user,
                boolean replacing) {
            CallbackInfo info = new CallbackInfo();
            info.packageNames = packageNames;
            info.replacing = replacing;
            info.user = user;
            obtainMessage(MSG_UNAVAILABLE, info).sendToTarget();
        }

        public void postOnPackagesSuspended(String[] packageNames, Bundle launcherExtras,
                UserHandle user) {
            CallbackInfo info = new CallbackInfo();
            info.packageNames = packageNames;
            info.user = user;
            info.launcherExtras = launcherExtras;
            obtainMessage(MSG_SUSPENDED, info).sendToTarget();
        }

        public void postOnPackagesUnsuspended(String[] packageNames, UserHandle user) {
            CallbackInfo info = new CallbackInfo();
            info.packageNames = packageNames;
            info.user = user;
            obtainMessage(MSG_UNSUSPENDED, info).sendToTarget();
        }

        public void postOnShortcutChanged(String packageName, UserHandle user,
                List<ShortcutInfo> shortcuts) {
            CallbackInfo info = new CallbackInfo();
            info.packageName = packageName;
            info.user = user;
            info.shortcuts = shortcuts;
            obtainMessage(MSG_SHORTCUT_CHANGED, info).sendToTarget();
        }
    }

    /**
     * Register a callback to watch for session lifecycle events in this user and managed profiles.
     * @param callback The callback to register.
     * @param executor {@link Executor} to handle the callbacks, cannot be null.
     *
     * @see PackageInstaller#registerSessionCallback(SessionCallback)
     */
    public void registerPackageInstallerSessionCallback(
            @NonNull @CallbackExecutor Executor executor, @NonNull SessionCallback callback) {
        if (executor == null) {
            throw new NullPointerException("Executor must not be null");
        }

        synchronized (mDelegates) {
            final SessionCallbackDelegate delegate = new SessionCallbackDelegate(callback,
                    executor);
            try {
                mService.registerPackageInstallerCallback(mContext.getPackageName(),
                        delegate);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
            mDelegates.add(delegate);
        }
    }

    /**
     * Unregisters a callback that was previously registered.
     *
     * @param callback The callback to unregister.
     * @see #registerPackageInstallerSessionCallback(Executor, SessionCallback)
     */
    public void unregisterPackageInstallerSessionCallback(@NonNull SessionCallback callback) {
        synchronized (mDelegates) {
            for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
                final SessionCallbackDelegate delegate = i.next();
                if (delegate.mCallback == callback) {
                    mPm.getPackageInstaller().unregisterSessionCallback(delegate.mCallback);
                    i.remove();
                }
            }
        }
    }

    /**
     * Return list of all known install sessions in this user and managed profiles, regardless
     * of the installer.
     *
     * @see PackageInstaller#getAllSessions()
     */
    public @NonNull List<SessionInfo> getAllPackageInstallerSessions() {
        try {
            return mService.getAllSessions(mContext.getPackageName()).getList();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * A helper method to extract a {@link PinItemRequest} set to
     * the {@link #EXTRA_PIN_ITEM_REQUEST} extra.
     */
    public PinItemRequest getPinItemRequest(Intent intent) {
        return intent.getParcelableExtra(EXTRA_PIN_ITEM_REQUEST);
    }

    /**
     * Represents a "pin shortcut" or a "pin appwidget" request made by an app, which is sent with
     * an {@link #ACTION_CONFIRM_PIN_SHORTCUT} or {@link #ACTION_CONFIRM_PIN_APPWIDGET} intent
     * respectively to the default launcher app.
     *
     * <h3>Request of the {@link #REQUEST_TYPE_SHORTCUT} type.
     *
     * <p>A {@link #REQUEST_TYPE_SHORTCUT} request represents a request to pin a
     * {@link ShortcutInfo}.  If the launcher accepts a request, call {@link #accept()},
     * or {@link #accept(Bundle)} with a null or empty Bundle.  No options are defined for
     * pin-shortcuts requests.
     *
     * <p>{@link #getShortcutInfo()} always returns a non-null {@link ShortcutInfo} for this type.
     *
     * <p>The launcher may receive a request with a {@link ShortcutInfo} that is already pinned, in
     * which case {@link ShortcutInfo#isPinned()} returns true.  This means the user wants to create
     * another pinned shortcut for a shortcut that's already pinned.  If the launcher accepts it,
     * {@link #accept()} must still be called even though the shortcut is already pinned, and
     * create a new pinned shortcut icon for it.
     *
     * <p>See also {@link ShortcutManager} for more details.
     *
     * <h3>Request of the {@link #REQUEST_TYPE_APPWIDGET} type.
     *
     * <p>A {@link #REQUEST_TYPE_SHORTCUT} request represents a request to pin a
     * an AppWidget.  If the launcher accepts a request, call {@link #accept(Bundle)} with
     * the appwidget integer ID set to the
     * {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID} extra.
     *
     * <p>{@link #getAppWidgetProviderInfo(Context)} always returns a non-null
     * {@link AppWidgetProviderInfo} for this type.
     *
     * <p>See also {@link AppWidgetManager} for more details.
     *
     * @see #EXTRA_PIN_ITEM_REQUEST
     * @see #getPinItemRequest(Intent)
     */
    public static final class PinItemRequest implements Parcelable {

        /** This is a request to pin shortcut. */
        public static final int REQUEST_TYPE_SHORTCUT = 1;

        /** This is a request to pin app widget. */
        public static final int REQUEST_TYPE_APPWIDGET = 2;

        /** @hide */
        @IntDef(prefix = { "REQUEST_TYPE_" }, value = {
                REQUEST_TYPE_SHORTCUT,
                REQUEST_TYPE_APPWIDGET
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface RequestType {}

        private final int mRequestType;
        private final IPinItemRequest mInner;

        /**
         * @hide
         */
        public PinItemRequest(IPinItemRequest inner, int type) {
            mInner = inner;
            mRequestType = type;
        }

        /**
         * Represents the type of a request, which is one of the {@code REQUEST_TYPE_} constants.
         *
         * @return one of the {@code REQUEST_TYPE_} constants.
         */
        @RequestType
        public int getRequestType() {
            return mRequestType;
        }

        /**
         * {@link ShortcutInfo} sent by the requesting app.
         * Always non-null for a {@link #REQUEST_TYPE_SHORTCUT} request, and always null for a
         * different request type.
         *
         * @return requested {@link ShortcutInfo} when a request is of the
         * {@link #REQUEST_TYPE_SHORTCUT} type.  Null otherwise.
         */
        @Nullable
        public ShortcutInfo getShortcutInfo() {
            try {
                return mInner.getShortcutInfo();
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }
        }

        /**
         * {@link AppWidgetProviderInfo} sent by the requesting app.
         * Always non-null for a {@link #REQUEST_TYPE_APPWIDGET} request, and always null for a
         * different request type.
         *
         * <p>Launcher should not show any configuration activity associated with the provider, and
         * assume that the widget is already fully configured. Upon accepting the widget, it should
         * pass the widgetId in {@link #accept(Bundle)}.
         *
         * @return requested {@link AppWidgetProviderInfo} when a request is of the
         * {@link #REQUEST_TYPE_APPWIDGET} type.  Null otherwise.
         */
        @Nullable
        public AppWidgetProviderInfo getAppWidgetProviderInfo(Context context) {
            try {
                final AppWidgetProviderInfo info = mInner.getAppWidgetProviderInfo();
                if (info == null) {
                    return null;
                }
                info.updateDimensions(context.getResources().getDisplayMetrics());
                return info;
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }
        }

        /**
         * Any extras sent by the requesting app.
         *
         * @return For a shortcut request, this method always return null.  For an AppWidget
         * request, this method returns the extras passed to the
         * {@link android.appwidget.AppWidgetManager#requestPinAppWidget(
         * ComponentName, Bundle, PendingIntent)} API.  See {@link AppWidgetManager} for details.
         */
        @Nullable
        public Bundle getExtras() {
            try {
                return mInner.getExtras();
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }
        }

        /**
         * Return whether a request is still valid.
         *
         * @return {@code TRUE} if a request is valid and {@link #accept(Bundle)} may be called.
         */
        public boolean isValid() {
            try {
                return mInner.isValid();
            } catch (RemoteException e) {
                return false;
            }
        }

        /**
         * Called by the receiving launcher app when the user accepts the request.
         *
         * @param options must be set for a {@link #REQUEST_TYPE_APPWIDGET} request.
         *
         * @return {@code TRUE} if the shortcut or the AppWidget has actually been pinned.
         * {@code FALSE} if the item hasn't been pinned, for example, because the request had
         * already been canceled, in which case the launcher must not pin the requested item.
         */
        public boolean accept(@Nullable Bundle options) {
            try {
                return mInner.accept(options);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }

        /**
         * Called by the receiving launcher app when the user accepts the request, with no options.
         *
         * @return {@code TRUE} if the shortcut or the AppWidget has actually been pinned.
         * {@code FALSE} if the item hasn't been pinned, for example, because the request had
         * already been canceled, in which case the launcher must not pin the requested item.
         */
        public boolean accept() {
            return accept(/* options= */ null);
        }

        private PinItemRequest(Parcel source) {
            final ClassLoader cl = getClass().getClassLoader();

            mRequestType = source.readInt();
            mInner = IPinItemRequest.Stub.asInterface(source.readStrongBinder());
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeInt(mRequestType);
            dest.writeStrongBinder(mInner.asBinder());
        }

        public static final @android.annotation.NonNull Creator<PinItemRequest> CREATOR =
                new Creator<PinItemRequest>() {
                    public PinItemRequest createFromParcel(Parcel source) {
                        return new PinItemRequest(source);
                    }
                    public PinItemRequest[] newArray(int size) {
                        return new PinItemRequest[size];
                    }
                };

        @Override
        public int describeContents() {
            return 0;
        }
    }

    /**
     * A class that encapsulates information about the usage limit set for an app or
     * a group of apps.
     *
     * <p>The launcher can query specifics about the usage limit such as how much usage time
     * the limit has and how much of the total usage time is remaining via the APIs available
     * in this class.
     *
     * @see #getAppUsageLimit(String, UserHandle)
     * @hide
     */
    @SystemApi
    public static final class AppUsageLimit implements Parcelable {
        private final long mTotalUsageLimit;
        private final long mUsageRemaining;

        /** @hide */
        public AppUsageLimit(long totalUsageLimit, long usageRemaining) {
            this.mTotalUsageLimit = totalUsageLimit;
            this.mUsageRemaining = usageRemaining;
        }

        /**
         * Returns the total usage limit in milliseconds set for an app or a group of apps.
         *
         * @return the total usage limit in milliseconds
         */
        public long getTotalUsageLimit() {
            return mTotalUsageLimit;
        }

        /**
         * Returns the usage remaining in milliseconds for an app or the group of apps
         * this limit refers to.
         *
         * @return the usage remaining in milliseconds
         */
        public long getUsageRemaining() {
            return mUsageRemaining;
        }

        private AppUsageLimit(Parcel source) {
            mTotalUsageLimit = source.readLong();
            mUsageRemaining = source.readLong();
        }

        public static final @android.annotation.NonNull Creator<AppUsageLimit> CREATOR = new Creator<AppUsageLimit>() {
            @Override
            public AppUsageLimit createFromParcel(Parcel source) {
                return new AppUsageLimit(source);
            }

            @Override
            public AppUsageLimit[] newArray(int size) {
                return new AppUsageLimit[size];
            }
        };

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeLong(mTotalUsageLimit);
            dest.writeLong(mUsageRemaining);
        }
    }
}
