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

Commit 480d532c authored by Pinyao Ting's avatar Pinyao Ting
Browse files

Replace oneway shortcut api with AndroidFuture

Oneway calls to the system process can cause more trouble along those
lines than they solve.

Asynchronous incall pressure to the system process is worse than
synchronous incall pressure: it causes catastrophic failure modes
and is also much harder to diagnose when problems happen.
It's also much harder to guarantee transactionality when the caller
side is asynchronous.

Bug: 184878227
Test: atest ShortcutManagerTest1 ShortcutManagerTest2
ShortcutManagerTest3 ShortcutManagerTest4 ShortcutManagerTest5
ShortcutManagerTest6 ShortcutManagerTest7 ShortcutManagerTest8
ShortcutManagerTest9 ShortcutManagerTest10 ShortcutManagerTest11
Test: atest CtsShortcutManagerTestCases
Change-Id: I4ec6b188f079c018902bedf32198c04e9c45a60d

Change-Id: I854de382ee6bdc5ae32b6874b7d875dfe6c03c40
parent d9b11089
Loading
Loading
Loading
Loading
+24 −25
Original line number Diff line number Diff line
@@ -26,29 +26,29 @@ import com.android.internal.infra.AndroidFuture;
/** {@hide} */
interface IShortcutService {

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

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

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

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

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

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

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

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

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

    int getMaxShortcutCountPerActivity(String packageName, int userId);

@@ -58,31 +58,30 @@ interface IShortcutService {

    int getIconMaxDimensions(String packageName, int userId);

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

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

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

    byte[] getBackupPayload(int user);

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

    boolean isRequestPinItemSupported(int user, int requestType);

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

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

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

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

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

    oneway void updateShortcutVisibility(String callingPkg, String packageName,
    AndroidFuture updateShortcutVisibility(String callingPkg, String packageName,
            in byte[] certificate, in boolean visible, int userId);
}
+53 −66
Original line number Diff line number Diff line
@@ -145,14 +145,13 @@ public class ShortcutManager {
     */
    @WorkerThread
    public boolean setDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
        final AndroidFuture<Boolean> future = new AndroidFuture<>();
        try {
            mService.setDynamicShortcuts(mContext.getPackageName(),
                    new ParceledListSlice(shortcutInfoList), injectMyUserId(), future);
            return ((boolean) getFutureOrThrow(mService.setDynamicShortcuts(
                    mContext.getPackageName(), new ParceledListSlice(
                            shortcutInfoList), injectMyUserId())));
        } catch (RemoteException e) {
            future.completeExceptionally(e);
            throw e.rethrowFromSystemServer();
        }
        return getFutureOrThrow(future);
    }

    /**
@@ -167,14 +166,12 @@ public class ShortcutManager {
    @WorkerThread
    @NonNull
    public List<ShortcutInfo> getDynamicShortcuts() {
        final AndroidFuture<ParceledListSlice<ShortcutInfo>> future = new AndroidFuture<>();
        try {
            mService.getShortcuts(mContext.getPackageName(), FLAG_MATCH_DYNAMIC, injectMyUserId(),
                    future);
            return getFutureOrThrow(mService.getShortcuts(mContext.getPackageName(),
                    FLAG_MATCH_DYNAMIC, injectMyUserId())).getList();
        } catch (RemoteException e) {
            future.completeExceptionally(e);
            throw e.rethrowFromSystemServer();
        }
        return getFutureOrThrow(future).getList();
    }

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

    /**
@@ -220,13 +215,12 @@ public class ShortcutManager {
    @WorkerThread
    @NonNull
    public List<ShortcutInfo> getShortcuts(@ShortcutMatchFlags int matchFlags) {
        final AndroidFuture<ParceledListSlice<ShortcutInfo>> future = new AndroidFuture<>();
        try {
            mService.getShortcuts(mContext.getPackageName(), matchFlags, injectMyUserId(), future);
            return getFutureOrThrow(mService.getShortcuts(mContext.getPackageName(), matchFlags,
                    injectMyUserId())).getList();
        } catch (RemoteException e) {
            future.completeExceptionally(e);
            throw e.rethrowFromSystemServer();
        }
        return getFutureOrThrow(future).getList();
    }

    /**
@@ -244,14 +238,13 @@ public class ShortcutManager {
     */
    @WorkerThread
    public boolean addDynamicShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
        final AndroidFuture<Boolean> future = new AndroidFuture<>();
        try {
            mService.addDynamicShortcuts(mContext.getPackageName(),
                    new ParceledListSlice(shortcutInfoList), injectMyUserId(), future);
            return (boolean) getFutureOrThrow(mService.addDynamicShortcuts(
                    mContext.getPackageName(), new ParceledListSlice(shortcutInfoList),
                    injectMyUserId()));
        } catch (RemoteException e) {
            future.completeExceptionally(e);
            throw e.rethrowFromSystemServer();
        }
        return getFutureOrThrow(future);
    }

    /**
@@ -261,8 +254,8 @@ public class ShortcutManager {
     */
    public void removeDynamicShortcuts(@NonNull List<String> shortcutIds) {
        try {
            mService.removeDynamicShortcuts(mContext.getPackageName(), shortcutIds,
                    injectMyUserId());
            getFutureOrThrow(mService.removeDynamicShortcuts(mContext.getPackageName(), shortcutIds,
                    injectMyUserId()));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -275,7 +268,8 @@ public class ShortcutManager {
     */
    public void removeAllDynamicShortcuts() {
        try {
            mService.removeAllDynamicShortcuts(mContext.getPackageName(), injectMyUserId());
            getFutureOrThrow(mService.removeAllDynamicShortcuts(mContext.getPackageName(),
                    injectMyUserId()));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -288,8 +282,8 @@ public class ShortcutManager {
     */
    public void removeLongLivedShortcuts(@NonNull List<String> shortcutIds) {
        try {
            mService.removeLongLivedShortcuts(mContext.getPackageName(), shortcutIds,
                    injectMyUserId());
            getFutureOrThrow(mService.removeLongLivedShortcuts(mContext.getPackageName(),
                    shortcutIds, injectMyUserId()));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -307,14 +301,12 @@ public class ShortcutManager {
    @WorkerThread
    @NonNull
    public List<ShortcutInfo> getPinnedShortcuts() {
        final AndroidFuture<ParceledListSlice<ShortcutInfo>> future = new AndroidFuture<>();
        try {
            mService.getShortcuts(mContext.getPackageName(), FLAG_MATCH_PINNED, injectMyUserId(),
                    future);
            return getFutureOrThrow(mService.getShortcuts(mContext.getPackageName(),
                    FLAG_MATCH_PINNED, injectMyUserId())).getList();
        } catch (RemoteException e) {
            future.completeExceptionally(e);
            throw e.rethrowFromSystemServer();
        }
        return getFutureOrThrow(future).getList();
    }

    /**
@@ -331,14 +323,12 @@ public class ShortcutManager {
     */
    @WorkerThread
    public boolean updateShortcuts(@NonNull List<ShortcutInfo> shortcutInfoList) {
        final AndroidFuture<Boolean> future = new AndroidFuture<>();
        try {
            mService.updateShortcuts(mContext.getPackageName(),
                    new ParceledListSlice(shortcutInfoList), injectMyUserId(), future);
            return (boolean) getFutureOrThrow(mService.updateShortcuts(mContext.getPackageName(),
                    new ParceledListSlice(shortcutInfoList), injectMyUserId()));
        } catch (RemoteException e) {
            future.completeExceptionally(e);
            throw e.rethrowFromSystemServer();
        }
        return getFutureOrThrow(future);
    }

    /**
@@ -352,9 +342,9 @@ public class ShortcutManager {
     */
    public void disableShortcuts(@NonNull List<String> shortcutIds) {
        try {
            mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
            getFutureOrThrow(mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
                    /* disabledMessage =*/ null, /* disabledMessageResId =*/ 0,
                    injectMyUserId());
                    injectMyUserId()));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -365,9 +355,9 @@ public class ShortcutManager {
     */
    public void disableShortcuts(@NonNull List<String> shortcutIds, int disabledMessageResId) {
        try {
            mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
            getFutureOrThrow(mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
                    /* disabledMessage =*/ null, disabledMessageResId,
                    injectMyUserId());
                    injectMyUserId()));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -393,9 +383,9 @@ public class ShortcutManager {
     */
    public void disableShortcuts(@NonNull List<String> shortcutIds, CharSequence disabledMessage) {
        try {
            mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
            getFutureOrThrow(mService.disableShortcuts(mContext.getPackageName(), shortcutIds,
                    disabledMessage, /* disabledMessageResId =*/ 0,
                    injectMyUserId());
                    injectMyUserId()));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -411,7 +401,8 @@ public class ShortcutManager {
     */
    public void enableShortcuts(@NonNull List<String> shortcutIds) {
        try {
            mService.enableShortcuts(mContext.getPackageName(), shortcutIds, injectMyUserId());
            getFutureOrThrow(mService.enableShortcuts(
                    mContext.getPackageName(), shortcutIds, injectMyUserId()));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -532,8 +523,8 @@ public class ShortcutManager {
     */
    public void reportShortcutUsed(String shortcutId) {
        try {
            mService.reportShortcutUsed(mContext.getPackageName(), shortcutId,
                    injectMyUserId());
            getFutureOrThrow(mService.reportShortcutUsed(mContext.getPackageName(), shortcutId,
                    injectMyUserId()));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -610,14 +601,12 @@ public class ShortcutManager {
    @WorkerThread
    public boolean requestPinShortcut(@NonNull ShortcutInfo shortcut,
            @Nullable IntentSender resultIntent) {
        final AndroidFuture<Boolean> future = new AndroidFuture<>();
        try {
            mService.requestPinShortcut(mContext.getPackageName(), shortcut,
                    resultIntent, injectMyUserId(), future);
            return (boolean) getFutureOrThrow(mService.requestPinShortcut(mContext.getPackageName(),
                    shortcut, resultIntent, injectMyUserId()));
        } catch (RemoteException e) {
            future.completeExceptionally(e);
            throw e.rethrowFromSystemServer();
        }
        return getFutureOrThrow(future);
    }

    /**
@@ -639,14 +628,12 @@ public class ShortcutManager {
     */
    @WorkerThread
    public Intent createShortcutResultIntent(@NonNull ShortcutInfo shortcut) {
        final AndroidFuture<Intent> future = new AndroidFuture<>();
        try {
            mService.createShortcutResultIntent(mContext.getPackageName(), shortcut,
                    injectMyUserId(), future);
            return getFutureOrThrow(mService.createShortcutResultIntent(mContext.getPackageName(),
                    shortcut, injectMyUserId()));
        } catch (RemoteException e) {
            future.completeExceptionally(e);
            throw e.rethrowFromSystemServer();
        }
        return getFutureOrThrow(future);
    }

    /**
@@ -659,7 +646,7 @@ public class ShortcutManager {
     */
    public void onApplicationActive(@NonNull String packageName, @UserIdInt int userId) {
        try {
            mService.onApplicationActive(packageName, userId);
            getFutureOrThrow(mService.onApplicationActive(packageName, userId));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -684,13 +671,12 @@ public class ShortcutManager {
    @SystemApi
    @RequiresPermission(Manifest.permission.MANAGE_APP_PREDICTIONS)
    public List<ShareShortcutInfo> getShareTargets(@NonNull IntentFilter filter) {
        final AndroidFuture<ParceledListSlice> future = new AndroidFuture<>();
        try {
            mService.getShareTargets(mContext.getPackageName(), filter, injectMyUserId(), future);
            return getFutureOrThrow(mService.getShareTargets(mContext.getPackageName(), filter,
                    injectMyUserId())).getList();
        } catch (RemoteException e) {
            future.completeExceptionally(e);
            throw e.rethrowFromSystemServer();
        }
        return getFutureOrThrow(future).getList();
    }

    /**
@@ -797,7 +783,8 @@ public class ShortcutManager {
     */
    public void pushDynamicShortcut(@NonNull ShortcutInfo shortcut) {
        try {
            mService.pushDynamicShortcut(mContext.getPackageName(), shortcut, injectMyUserId());
            getFutureOrThrow(mService.pushDynamicShortcut(
                    mContext.getPackageName(), shortcut, injectMyUserId()));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -813,8 +800,8 @@ public class ShortcutManager {
    public void updateShortcutVisibility(@NonNull final String packageName,
            @Nullable final byte[] certificate, final boolean visible) {
        try {
            mService.updateShortcutVisibility(mContext.getPackageName(), packageName, certificate,
                    visible, injectMyUserId());
            getFutureOrThrow(mService.updateShortcutVisibility(mContext.getPackageName(),
                    packageName, certificate, visible, injectMyUserId()));
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+7 −7
Original line number Diff line number Diff line
@@ -158,6 +158,8 @@ class ShortcutPackage extends ShortcutPackageItem {
    private static final String KEY_BITMAPS = "bitmaps";
    private static final String KEY_BITMAP_BYTES = "bitmapBytes";

    private final Object mLock = new Object();

    /**
     * An temp in-memory copy of shortcuts for this package that was loaded from xml, keyed on IDs.
     */
@@ -168,6 +170,11 @@ class ShortcutPackage extends ShortcutPackageItem {
     */
    private final ArrayList<ShareTargetInfo> mShareTargets = new ArrayList<>(0);

    /**
     * All external packages that have gained access to the shortcuts from this package
     */
    private final Map<String, PackageIdentifier> mPackageIdentifiers = new ArrayMap<>(0);

    /**
     * # of times the package has called rate-limited APIs.
     */
@@ -182,13 +189,6 @@ class ShortcutPackage extends ShortcutPackageItem {

    private long mLastKnownForegroundElapsedTime;

    private final Object mLock = new Object();

    /**
     * All external packages that have gained access to the shortcuts from this package
     */
    private final Map<String, PackageIdentifier> mPackageIdentifiers = new ArrayMap<>(0);

    private boolean mIsInitilized;

    private ShortcutPackage(ShortcutUser shortcutUser,
+720 −517

File changed.

Preview size limit exceeded, changes collapsed.