Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94582324 authored by Pinyao Ting's avatar Pinyao Ting
Browse files

Shortcut integration with AppSearch (part 4)

To prevent starving binder thread over synchrounous operation, following
changes were made in this CL:
1, Create oneway apis in aidl
2. Annotation to ensure existing api call are running in WorkerThread

Bug: 180558621
NoNonSdkCheck: ShortcutService is for internal use, not a public api.
It should have been put in block-list in the first place.
Test: no change in functionality, covered by existing unit/cts tests
Change-Id: I17ecbaa7f2da30babec9fd58af7f07d5c0594054
parent 26f84ed6
Loading
Loading
Loading
Loading
+9 −9
Original line number Original line Diff line number Diff line
@@ -12877,18 +12877,18 @@ package android.content.pm {
  }
  }
  public class ShortcutManager {
  public class ShortcutManager {
    method public boolean addDynamicShortcuts(@NonNull java.util.List<android.content.pm.ShortcutInfo>);
    method @WorkerThread public boolean addDynamicShortcuts(@NonNull java.util.List<android.content.pm.ShortcutInfo>);
    method public android.content.Intent createShortcutResultIntent(@NonNull android.content.pm.ShortcutInfo);
    method @WorkerThread public android.content.Intent createShortcutResultIntent(@NonNull android.content.pm.ShortcutInfo);
    method public void disableShortcuts(@NonNull java.util.List<java.lang.String>);
    method public void disableShortcuts(@NonNull java.util.List<java.lang.String>);
    method public void disableShortcuts(@NonNull java.util.List<java.lang.String>, CharSequence);
    method public void disableShortcuts(@NonNull java.util.List<java.lang.String>, CharSequence);
    method public void enableShortcuts(@NonNull java.util.List<java.lang.String>);
    method public void enableShortcuts(@NonNull java.util.List<java.lang.String>);
    method @NonNull public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
    method @NonNull @WorkerThread public java.util.List<android.content.pm.ShortcutInfo> getDynamicShortcuts();
    method public int getIconMaxHeight();
    method public int getIconMaxHeight();
    method public int getIconMaxWidth();
    method public int getIconMaxWidth();
    method @NonNull public java.util.List<android.content.pm.ShortcutInfo> getManifestShortcuts();
    method @NonNull @WorkerThread public java.util.List<android.content.pm.ShortcutInfo> getManifestShortcuts();
    method public int getMaxShortcutCountPerActivity();
    method public int getMaxShortcutCountPerActivity();
    method @NonNull public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
    method @NonNull @WorkerThread public java.util.List<android.content.pm.ShortcutInfo> getPinnedShortcuts();
    method @NonNull public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(int);
    method @NonNull @WorkerThread public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(int);
    method public boolean isRateLimitingActive();
    method public boolean isRateLimitingActive();
    method public boolean isRequestPinShortcutSupported();
    method public boolean isRequestPinShortcutSupported();
    method public void pushDynamicShortcut(@NonNull android.content.pm.ShortcutInfo);
    method public void pushDynamicShortcut(@NonNull android.content.pm.ShortcutInfo);
@@ -12896,10 +12896,10 @@ package android.content.pm {
    method public void removeDynamicShortcuts(@NonNull java.util.List<java.lang.String>);
    method public void removeDynamicShortcuts(@NonNull java.util.List<java.lang.String>);
    method public void removeLongLivedShortcuts(@NonNull java.util.List<java.lang.String>);
    method public void removeLongLivedShortcuts(@NonNull java.util.List<java.lang.String>);
    method public void reportShortcutUsed(String);
    method public void reportShortcutUsed(String);
    method public boolean requestPinShortcut(@NonNull android.content.pm.ShortcutInfo, @Nullable android.content.IntentSender);
    method @WorkerThread public boolean requestPinShortcut(@NonNull android.content.pm.ShortcutInfo, @Nullable android.content.IntentSender);
    method public boolean setDynamicShortcuts(@NonNull java.util.List<android.content.pm.ShortcutInfo>);
    method @WorkerThread public boolean setDynamicShortcuts(@NonNull java.util.List<android.content.pm.ShortcutInfo>);
    method public void updateShortcutVisibility(@NonNull String, @Nullable byte[], boolean);
    method public void updateShortcutVisibility(@NonNull String, @Nullable byte[], boolean);
    method public boolean updateShortcuts(@NonNull java.util.List<android.content.pm.ShortcutInfo>);
    method @WorkerThread public boolean updateShortcuts(@NonNull java.util.List<android.content.pm.ShortcutInfo>);
    field public static final int FLAG_MATCH_CACHED = 8; // 0x8
    field public static final int FLAG_MATCH_CACHED = 8; // 0x8
    field public static final int FLAG_MATCH_DYNAMIC = 2; // 0x2
    field public static final int FLAG_MATCH_DYNAMIC = 2; // 0x2
    field public static final int FLAG_MATCH_MANIFEST = 1; // 0x1
    field public static final int FLAG_MATCH_MANIFEST = 1; // 0x1
+1 −1
Original line number Original line Diff line number Diff line
@@ -2687,7 +2687,7 @@ package android.content.pm {
  }
  }
  public class ShortcutManager {
  public class ShortcutManager {
    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_APP_PREDICTIONS) public java.util.List<android.content.pm.ShortcutManager.ShareShortcutInfo> getShareTargets(@NonNull android.content.IntentFilter);
    method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_APP_PREDICTIONS) @WorkerThread public java.util.List<android.content.pm.ShortcutManager.ShareShortcutInfo> getShareTargets(@NonNull android.content.IntentFilter);
    method public boolean hasShareTargets(@NonNull String);
    method public boolean hasShareTargets(@NonNull String);
  }
  }
+31 −27
Original line number Original line Diff line number Diff line
@@ -21,32 +21,34 @@ import android.content.IntentSender;
import android.content.pm.ParceledListSlice;
import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutInfo;


/**
import com.android.internal.infra.AndroidFuture;
 * {@hide}

 */
/** {@hide} */
interface IShortcutService {
interface IShortcutService {


    boolean setDynamicShortcuts(String packageName, in ParceledListSlice shortcutInfoList,
    oneway void setDynamicShortcuts(String packageName, in ParceledListSlice shortcutInfoList,
            int userId);
            int userId, in AndroidFuture callback);


    boolean addDynamicShortcuts(String packageName, in ParceledListSlice shortcutInfoList,
    oneway void addDynamicShortcuts(String packageName, in ParceledListSlice shortcutInfoList,
            int userId);
            int userId, in AndroidFuture callback);


    void removeDynamicShortcuts(String packageName, in List shortcutIds, int userId);
    oneway void removeDynamicShortcuts(String packageName, in List shortcutIds, int userId);


    void removeAllDynamicShortcuts(String packageName, int userId);
    oneway void removeAllDynamicShortcuts(String packageName, int userId);


    boolean updateShortcuts(String packageName, in ParceledListSlice shortcuts, int userId);
    oneway void updateShortcuts(String packageName, in ParceledListSlice shortcuts, int userId,
            in AndroidFuture callback);


    boolean requestPinShortcut(String packageName, in ShortcutInfo shortcut,
    oneway void requestPinShortcut(String packageName, in ShortcutInfo shortcut,
            in IntentSender resultIntent, int userId);
            in IntentSender resultIntent, int userId, in AndroidFuture callback);


    Intent createShortcutResultIntent(String packageName, in ShortcutInfo shortcut, int userId);
    oneway void createShortcutResultIntent(String packageName, in ShortcutInfo shortcut,
            int userId, in AndroidFuture callback);


    void disableShortcuts(String packageName, in List shortcutIds, CharSequence disabledMessage,
    oneway void disableShortcuts(String packageName, in List shortcutIds,
            int disabledMessageResId, int userId);
            CharSequence disabledMessage, int disabledMessageResId, int userId);


    void enableShortcuts(String packageName, in List shortcutIds, int userId);
    oneway void enableShortcuts(String packageName, in List shortcutIds, int userId);


    int getMaxShortcutCountPerActivity(String packageName, int userId);
    int getMaxShortcutCountPerActivity(String packageName, int userId);


@@ -56,29 +58,31 @@ interface IShortcutService {


    int getIconMaxDimensions(String packageName, int userId);
    int getIconMaxDimensions(String packageName, int userId);


    void reportShortcutUsed(String packageName, String shortcutId, int userId);
    oneway void reportShortcutUsed(String packageName, String shortcutId, int userId);


    void resetThrottling(); // system only API for developer opsions
    oneway void resetThrottling(); // system only API for developer opsions


    void onApplicationActive(String packageName, int userId); // system only API for sysUI
    oneway void onApplicationActive(String packageName, int userId); // system only API for sysUI


    byte[] getBackupPayload(int user);
    byte[] getBackupPayload(int user);


    void applyRestore(in byte[] payload, int user);
    oneway void applyRestore(in byte[] payload, int user);


    boolean isRequestPinItemSupported(int user, int requestType);
    boolean isRequestPinItemSupported(int user, int requestType);


    // System API used by framework's ShareSheet (ChooserActivity)
    // System API used by framework's ShareSheet (ChooserActivity)
    ParceledListSlice getShareTargets(String packageName, in IntentFilter filter, int userId);
    oneway void getShareTargets(String packageName, in IntentFilter filter, int userId,
           in AndroidFuture<ParceledListSlice> callback);


    boolean hasShareTargets(String packageName, String packageToCheck, int userId);
    boolean hasShareTargets(String packageName, String packageToCheck, int userId);


    void removeLongLivedShortcuts(String packageName, in List shortcutIds, int userId);
    oneway void removeLongLivedShortcuts(String packageName, in List shortcutIds, int userId);


    ParceledListSlice getShortcuts(String packageName, int matchFlags, int userId);
    oneway void getShortcuts(String packageName, int matchFlags, int userId,
            in AndroidFuture<ParceledListSlice<ShortcutInfo>> callback);


    void pushDynamicShortcut(String packageName, in ShortcutInfo shortcut, int userId);
    oneway void pushDynamicShortcut(String packageName, in ShortcutInfo shortcut, int userId);


    void updateShortcutVisibility(String callingPkg, String packageName, in byte[] certificate,
    oneway void updateShortcutVisibility(String callingPkg, String packageName,
            in boolean visible, int userId);
            in byte[] certificate, in boolean visible, int userId);
}
}
+78 −30
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.Notification;
import android.app.Notification;
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.compat.annotation.UnsupportedAppUsage;
@@ -42,10 +43,12 @@ import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserHandle;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.infra.AndroidFuture;


import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.List;
import java.util.concurrent.ExecutionException;


/**
/**
 * <p><code>ShortcutManager</code> executes operations on an app's set of <i>shortcuts</i>, which
 * <p><code>ShortcutManager</code> executes operations on an app's set of <i>shortcuts</i>, which
@@ -140,13 +143,16 @@ public class ShortcutManager {
     *
     *
     * @throws IllegalStateException when the user is locked.
     * @throws IllegalStateException when the user is locked.
     */
     */
    @WorkerThread
    public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
    public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
        final AndroidFuture<Boolean> future = new AndroidFuture<>();
        try {
        try {
            return mService.setDynamicShortcuts(mContext.getPackageName(),
            mService.setDynamicShortcuts(mContext.getPackageName(),
                    new ParceledListSlice(shortcutInfoList), injectMyUserId());
                    new ParceledListSlice(shortcutInfoList), injectMyUserId(), future);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            future.completeExceptionally(e);
        }
        }
        return getFutureOrThrow(future);
    }
    }


    /**
    /**
@@ -158,14 +164,17 @@ public class ShortcutManager {
     *
     *
     * @throws IllegalStateException when the user is locked.
     * @throws IllegalStateException when the user is locked.
     */
     */
    @WorkerThread
    @NonNull
    @NonNull
    public List<ShortcutInfo> getDynamicShortcuts() {
    public List<ShortcutInfo> getDynamicShortcuts() {
        final AndroidFuture<ParceledListSlice<ShortcutInfo>> future = new AndroidFuture<>();
        try {
        try {
            return mService.getShortcuts(mContext.getPackageName(), FLAG_MATCH_DYNAMIC,
            mService.getShortcuts(mContext.getPackageName(), FLAG_MATCH_DYNAMIC, injectMyUserId(),
                    injectMyUserId()).getList();
                    future);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            future.completeExceptionally(e);
        }
        }
        return getFutureOrThrow(future).getList();
    }
    }


    /**
    /**
@@ -177,14 +186,17 @@ public class ShortcutManager {
     *
     *
     * @throws IllegalStateException when the user is locked.
     * @throws IllegalStateException when the user is locked.
     */
     */
    @WorkerThread
    @NonNull
    @NonNull
    public List<ShortcutInfo> getManifestShortcuts() {
    public List<ShortcutInfo> getManifestShortcuts() {
        final AndroidFuture<ParceledListSlice<ShortcutInfo>> future = new AndroidFuture<>();
        try {
        try {
            return mService.getShortcuts(mContext.getPackageName(), FLAG_MATCH_MANIFEST,
            mService.getShortcuts(mContext.getPackageName(), FLAG_MATCH_MANIFEST, injectMyUserId(),
                    injectMyUserId()).getList();
                    future);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            future.completeExceptionally(e);
        }
        }
        return getFutureOrThrow(future).getList();
    }
    }


    /**
    /**
@@ -205,14 +217,16 @@ public class ShortcutManager {
     *
     *
     * @throws IllegalStateException when the user is locked.
     * @throws IllegalStateException when the user is locked.
     */
     */
    @WorkerThread
    @NonNull
    @NonNull
    public List<ShortcutInfo> getShortcuts(@ShortcutMatchFlags int matchFlags) {
    public List<ShortcutInfo> getShortcuts(@ShortcutMatchFlags int matchFlags) {
        final AndroidFuture<ParceledListSlice<ShortcutInfo>> future = new AndroidFuture<>();
        try {
        try {
            return mService.getShortcuts(mContext.getPackageName(), matchFlags, injectMyUserId())
            mService.getShortcuts(mContext.getPackageName(), matchFlags, injectMyUserId(), future);
                    .getList();
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            future.completeExceptionally(e);
        }
        }
        return getFutureOrThrow(future).getList();
    }
    }


    /**
    /**
@@ -228,13 +242,16 @@ public class ShortcutManager {
     *
     *
     * @throws IllegalStateException when the user is locked.
     * @throws IllegalStateException when the user is locked.
     */
     */
    @WorkerThread
    public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
    public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
        final AndroidFuture<Boolean> future = new AndroidFuture<>();
        try {
        try {
            return mService.addDynamicShortcuts(mContext.getPackageName(),
            mService.addDynamicShortcuts(mContext.getPackageName(),
                    new ParceledListSlice(shortcutInfoList), injectMyUserId());
                    new ParceledListSlice(shortcutInfoList), injectMyUserId(), future);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            future.completeExceptionally(e);
        }
        }
        return getFutureOrThrow(future);
    }
    }


    /**
    /**
@@ -287,14 +304,17 @@ public class ShortcutManager {
     *
     *
     * @throws IllegalStateException when the user is locked.
     * @throws IllegalStateException when the user is locked.
     */
     */
    @WorkerThread
    @NonNull
    @NonNull
    public List<ShortcutInfo> getPinnedShortcuts() {
    public List<ShortcutInfo> getPinnedShortcuts() {
        final AndroidFuture<ParceledListSlice<ShortcutInfo>> future = new AndroidFuture<>();
        try {
        try {
            return mService.getShortcuts(mContext.getPackageName(), FLAG_MATCH_PINNED,
            mService.getShortcuts(mContext.getPackageName(), FLAG_MATCH_PINNED, injectMyUserId(),
                    injectMyUserId()).getList();
                    future);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            future.completeExceptionally(e);
        }
        }
        return getFutureOrThrow(future).getList();
    }
    }


    /**
    /**
@@ -309,13 +329,16 @@ public class ShortcutManager {
     *
     *
     * @throws IllegalStateException when the user is locked.
     * @throws IllegalStateException when the user is locked.
     */
     */
    @WorkerThread
    public boolean updateShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
    public boolean updateShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
        final AndroidFuture<Boolean> future = new AndroidFuture<>();
        try {
        try {
            return mService.updateShortcuts(mContext.getPackageName(),
            mService.updateShortcuts(mContext.getPackageName(),
                    new ParceledListSlice(shortcutInfoList), injectMyUserId());
                    new ParceledListSlice(shortcutInfoList), injectMyUserId(), future);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            future.completeExceptionally(e);
        }
        }
        return getFutureOrThrow(future);
    }
    }


    /**
    /**
@@ -584,14 +607,17 @@ public class ShortcutManager {
     * @throws IllegalStateException The caller doesn't have a foreground activity or a foreground
     * @throws IllegalStateException The caller doesn't have a foreground activity or a foreground
     * service, or the device is locked.
     * service, or the device is locked.
     */
     */
    @WorkerThread
    public boolean requestPinShortcut(@NonNull ShortcutInfo shortcut,
    public boolean requestPinShortcut(@NonNull ShortcutInfo shortcut,
            @Nullable IntentSender resultIntent) {
            @Nullable IntentSender resultIntent) {
        final AndroidFuture<Boolean> future = new AndroidFuture<>();
        try {
        try {
            return mService.requestPinShortcut(mContext.getPackageName(), shortcut,
            mService.requestPinShortcut(mContext.getPackageName(), shortcut,
                    resultIntent, injectMyUserId());
                    resultIntent, injectMyUserId(), future);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            future.completeExceptionally(e);
        }
        }
        return getFutureOrThrow(future);
    }
    }


    /**
    /**
@@ -611,13 +637,16 @@ public class ShortcutManager {
     *
     *
     * @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled.
     * @throws IllegalArgumentException if a shortcut with the same ID exists and is disabled.
     */
     */
    @WorkerThread
    public Intent createShortcutResultIntent(@NonNull ShortcutInfo shortcut) {
    public Intent createShortcutResultIntent(@NonNull ShortcutInfo shortcut) {
        final AndroidFuture<Intent> future = new AndroidFuture<>();
        try {
        try {
            return mService.createShortcutResultIntent(mContext.getPackageName(), shortcut,
            mService.createShortcutResultIntent(mContext.getPackageName(), shortcut,
                    injectMyUserId());
                    injectMyUserId(), future);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            future.completeExceptionally(e);
        }
        }
        return getFutureOrThrow(future);
    }
    }


    /**
    /**
@@ -650,16 +679,18 @@ public class ShortcutManager {
     * @return List of {@link ShareShortcutInfo}s that match the given IntentFilter.
     * @return List of {@link ShareShortcutInfo}s that match the given IntentFilter.
     * @hide
     * @hide
     */
     */
    @WorkerThread
    @NonNull
    @NonNull
    @SystemApi
    @SystemApi
    @RequiresPermission(Manifest.permission.MANAGE_APP_PREDICTIONS)
    @RequiresPermission(Manifest.permission.MANAGE_APP_PREDICTIONS)
    public List<ShareShortcutInfo> getShareTargets(@NonNull IntentFilter filter) {
    public List<ShareShortcutInfo> getShareTargets(@NonNull IntentFilter filter) {
        final AndroidFuture<ParceledListSlice> future = new AndroidFuture<>();
        try {
        try {
            return mService.getShareTargets(mContext.getPackageName(), filter,
            mService.getShareTargets(mContext.getPackageName(), filter, injectMyUserId(), future);
                    injectMyUserId()).getList();
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
            future.completeExceptionally(e);
        }
        }
        return getFutureOrThrow(future).getList();
    }
    }


    /**
    /**
@@ -788,4 +819,21 @@ public class ShortcutManager {
            throw e.rethrowFromSystemServer();
            throw e.rethrowFromSystemServer();
        }
        }
    }
    }

    private static <T> T getFutureOrThrow(@NonNull AndroidFuture<T> future) {
        try {
            return future.get();
        } catch (Throwable e) {
            if (e instanceof ExecutionException) {
                e = e.getCause();
            }
            if (e instanceof RuntimeException) {
                throw (RuntimeException) e;
            }
            if (e instanceof Error) {
                throw (Error) e;
            }
            throw new RuntimeException(e);
        }
    }
}
}
+39 −26
Original line number Original line Diff line number Diff line
@@ -103,6 +103,7 @@ import android.view.IWindowManager;


import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.CollectionUtils;
@@ -142,6 +143,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Collections;
import java.util.List;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Predicate;
@@ -1875,8 +1877,8 @@ public class ShortcutService extends IShortcutService.Stub {
    // === APIs ===
    // === APIs ===


    @Override
    @Override
    public boolean setDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList,
    public void setDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList,
            @UserIdInt int userId) {
            @UserIdInt int userId, @NonNull AndroidFuture callback) {
        verifyCaller(packageName, userId);
        verifyCaller(packageName, userId);


        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
@@ -1903,7 +1905,7 @@ public class ShortcutService extends IShortcutService.Stub {


            // Throttling.
            // Throttling.
            if (!ps.tryApiCall(unlimited)) {
            if (!ps.tryApiCall(unlimited)) {
                return false;
                callback.complete(false);
            }
            }


            // Initialize the implicit ranks for ShortcutPackage.adjustRanks().
            // Initialize the implicit ranks for ShortcutPackage.adjustRanks().
@@ -1939,12 +1941,12 @@ public class ShortcutService extends IShortcutService.Stub {


        verifyStates();
        verifyStates();


        return true;
        callback.complete(true);
    }
    }


    @Override
    @Override
    public boolean updateShortcuts(String packageName, ParceledListSlice shortcutInfoList,
    public void updateShortcuts(String packageName, ParceledListSlice shortcutInfoList,
            @UserIdInt int userId) {
            @UserIdInt int userId, AndroidFuture callback) {
        verifyCaller(packageName, userId);
        verifyCaller(packageName, userId);


        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
@@ -1971,7 +1973,8 @@ public class ShortcutService extends IShortcutService.Stub {


            // Throttling.
            // Throttling.
            if (!ps.tryApiCall(unlimited)) {
            if (!ps.tryApiCall(unlimited)) {
                return false;
                callback.complete(false);
                return;
            }
            }


            // Initialize the implicit ranks for ShortcutPackage.adjustRanks().
            // Initialize the implicit ranks for ShortcutPackage.adjustRanks().
@@ -2036,12 +2039,12 @@ public class ShortcutService extends IShortcutService.Stub {


        verifyStates();
        verifyStates();


        return true;
        callback.complete(true);
    }
    }


    @Override
    @Override
    public boolean  addDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList,
    public void addDynamicShortcuts(String packageName, ParceledListSlice shortcutInfoList,
            @UserIdInt int userId) {
            @UserIdInt int userId, AndroidFuture callback) {
        verifyCaller(packageName, userId);
        verifyCaller(packageName, userId);


        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
@@ -2071,7 +2074,8 @@ public class ShortcutService extends IShortcutService.Stub {


            // Throttling.
            // Throttling.
            if (!ps.tryApiCall(unlimited)) {
            if (!ps.tryApiCall(unlimited)) {
                return false;
                callback.complete(false);
                return;
            }
            }
            for (int i = 0; i < size; i++) {
            for (int i = 0; i < size; i++) {
                final ShortcutInfo newShortcut = newShortcuts.get(i);
                final ShortcutInfo newShortcut = newShortcuts.get(i);
@@ -2099,7 +2103,7 @@ public class ShortcutService extends IShortcutService.Stub {


        verifyStates();
        verifyStates();


        return true;
        callback.complete(true);
    }
    }


    @Override
    @Override
@@ -2164,15 +2168,17 @@ public class ShortcutService extends IShortcutService.Stub {
    }
    }


    @Override
    @Override
    public boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
    public void requestPinShortcut(String packageName, ShortcutInfo shortcut,
            IntentSender resultIntent, int userId) {
            IntentSender resultIntent, int userId, AndroidFuture callback) {
        Objects.requireNonNull(shortcut);
        Objects.requireNonNull(shortcut);
        Objects.requireNonNull(callback);
        Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled");
        Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled");
        return requestPinItem(packageName, userId, shortcut, null, null, resultIntent);
        callback.complete(requestPinItem(packageName, userId, shortcut, null, null, resultIntent));
    }
    }


    @Override
    @Override
    public Intent createShortcutResultIntent(String packageName, ShortcutInfo shortcut, int userId)
    public void createShortcutResultIntent(String packageName, ShortcutInfo shortcut, int userId,
            AndroidFuture callback)
            throws RemoteException {
            throws RemoteException {
        Objects.requireNonNull(shortcut);
        Objects.requireNonNull(shortcut);
        Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled");
        Preconditions.checkArgument(shortcut.isEnabled(), "Shortcut must be enabled");
@@ -2188,7 +2194,7 @@ public class ShortcutService extends IShortcutService.Stub {
        }
        }


        verifyStates();
        verifyStates();
        return ret;
        callback.complete(ret);
    }
    }


    /**
    /**
@@ -2445,8 +2451,9 @@ public class ShortcutService extends IShortcutService.Stub {
    }
    }


    @Override
    @Override
    public ParceledListSlice<ShortcutInfo> getShortcuts(String packageName,
    public void getShortcuts(String packageName,
            @ShortcutManager.ShortcutMatchFlags int matchFlags, @UserIdInt int userId) {
            @ShortcutManager.ShortcutMatchFlags int matchFlags, @UserIdInt int userId,
            AndroidFuture<ParceledListSlice<ShortcutInfo>> callback) {
        verifyCaller(packageName, userId);
        verifyCaller(packageName, userId);


        synchronized (mLock) {
        synchronized (mLock) {
@@ -2462,16 +2469,16 @@ public class ShortcutService extends IShortcutService.Stub {
                    | (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0)
                    | (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0)
                    | (matchCached ? ShortcutInfo.FLAG_CACHED_ALL : 0);
                    | (matchCached ? ShortcutInfo.FLAG_CACHED_ALL : 0);


            return getShortcutsWithQueryLocked(
            callback.complete(getShortcutsWithQueryLocked(
                    packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
                    packageName, userId, ShortcutInfo.CLONE_REMOVE_FOR_CREATOR,
                    (ShortcutInfo si) ->
                    (ShortcutInfo si) ->
                            si.isVisibleToPublisher() && (si.getFlags() & shortcutFlags) != 0);
                            si.isVisibleToPublisher() && (si.getFlags() & shortcutFlags) != 0));
        }
        }
    }
    }


    @Override
    @Override
    public ParceledListSlice<ShortcutManager.ShareShortcutInfo> getShareTargets(String packageName,
    public void getShareTargets(String packageName, IntentFilter filter, @UserIdInt int userId,
            IntentFilter filter, @UserIdInt int userId) {
            AndroidFuture<ParceledListSlice> callback) {
        Preconditions.checkStringNotEmpty(packageName, "packageName");
        Preconditions.checkStringNotEmpty(packageName, "packageName");
        Objects.requireNonNull(filter, "intentFilter");
        Objects.requireNonNull(filter, "intentFilter");


@@ -2487,7 +2494,7 @@ public class ShortcutService extends IShortcutService.Stub {
            final ShortcutUser user = getUserShortcutsLocked(userId);
            final ShortcutUser user = getUserShortcutsLocked(userId);
            user.forAllPackages(p -> shortcutInfoList.addAll(p.getMatchingShareTargets(filter)));
            user.forAllPackages(p -> shortcutInfoList.addAll(p.getMatchingShareTargets(filter)));


            return new ParceledListSlice<>(shortcutInfoList);
            callback.complete(new ParceledListSlice<>(shortcutInfoList));
        }
        }
    }
    }


@@ -3071,8 +3078,14 @@ public class ShortcutService extends IShortcutService.Stub {
        @Override
        @Override
        public List<ShortcutManager.ShareShortcutInfo> getShareTargets(
        public List<ShortcutManager.ShareShortcutInfo> getShareTargets(
                @NonNull String callingPackage, @NonNull IntentFilter intentFilter, int userId) {
                @NonNull String callingPackage, @NonNull IntentFilter intentFilter, int userId) {
            return ShortcutService.this.getShareTargets(
            final AndroidFuture<ParceledListSlice> future = new AndroidFuture<>();
                    callingPackage, intentFilter, userId).getList();
            ShortcutService.this.getShareTargets(
                    callingPackage, intentFilter, userId, future);
            try {
                return future.get().getList();
            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException(e);
            }
        }
        }


        @Override
        @Override