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
This commit is contained in:
Pinyao Ting
2021-04-13 09:46:40 -07:00
parent d9b11089e7
commit 480d532c96
4 changed files with 885 additions and 696 deletions

View File

@@ -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);
}

View File

@@ -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();
}

View File

@@ -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,

File diff suppressed because it is too large Load Diff