diff --git a/api/current.txt b/api/current.txt index c0fd25b1fdd8733c1d5ceb830ea49035af9cc4b9..5263c26258dfedc6f884c952a70e873577c6f7d4 100644 --- a/api/current.txt +++ b/api/current.txt @@ -10066,6 +10066,7 @@ package android.content.pm { method public android.os.PersistableBundle getExtras(); method public java.lang.String getId(); method public android.content.Intent getIntent(); + method public android.content.Intent getIntents(); method public long getLastChangedTimestamp(); method public java.lang.CharSequence getLongLabel(); method public java.lang.String getPackage(); @@ -10092,6 +10093,7 @@ package android.content.pm { method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle); method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon); method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent); + method public android.content.pm.ShortcutInfo.Builder setIntents(android.content.Intent[]); method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence); method public android.content.pm.ShortcutInfo.Builder setRank(int); method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence); @@ -10108,6 +10110,7 @@ package android.content.pm { method public java.util.List getManifestShortcuts(); method public int getMaxShortcutCountPerActivity(); method public java.util.List getPinnedShortcuts(); + method public boolean isRateLimitingActive(); method public void removeAllDynamicShortcuts(); method public void removeDynamicShortcuts(java.util.List); method public void reportShortcutUsed(java.lang.String); diff --git a/api/system-current.txt b/api/system-current.txt index e407eb4dc7f89eb8d3df209d2dd9f21195d77fcb..07a88252d9427ffeecfc3a9cea387f12e58e2f43 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -10491,6 +10491,7 @@ package android.content.pm { method public android.os.PersistableBundle getExtras(); method public java.lang.String getId(); method public android.content.Intent getIntent(); + method public android.content.Intent getIntents(); method public long getLastChangedTimestamp(); method public java.lang.CharSequence getLongLabel(); method public java.lang.String getPackage(); @@ -10517,6 +10518,7 @@ package android.content.pm { method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle); method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon); method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent); + method public android.content.pm.ShortcutInfo.Builder setIntents(android.content.Intent[]); method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence); method public android.content.pm.ShortcutInfo.Builder setRank(int); method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence); @@ -10533,6 +10535,7 @@ package android.content.pm { method public java.util.List getManifestShortcuts(); method public int getMaxShortcutCountPerActivity(); method public java.util.List getPinnedShortcuts(); + method public boolean isRateLimitingActive(); method public void removeAllDynamicShortcuts(); method public void removeDynamicShortcuts(java.util.List); method public void reportShortcutUsed(java.lang.String); diff --git a/api/test-current.txt b/api/test-current.txt index 53f87f4a3af6c66687922d9e6c45c9c648a8a5b8..9256ba431e09c6fc48745ed3be725eb266b9921a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -10079,6 +10079,7 @@ package android.content.pm { method public android.os.PersistableBundle getExtras(); method public java.lang.String getId(); method public android.content.Intent getIntent(); + method public android.content.Intent getIntents(); method public long getLastChangedTimestamp(); method public java.lang.CharSequence getLongLabel(); method public java.lang.String getPackage(); @@ -10105,6 +10106,7 @@ package android.content.pm { method public android.content.pm.ShortcutInfo.Builder setExtras(android.os.PersistableBundle); method public android.content.pm.ShortcutInfo.Builder setIcon(android.graphics.drawable.Icon); method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent); + method public android.content.pm.ShortcutInfo.Builder setIntents(android.content.Intent[]); method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence); method public android.content.pm.ShortcutInfo.Builder setRank(int); method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence); @@ -10122,6 +10124,7 @@ package android.content.pm { method public java.util.List getManifestShortcuts(); method public int getMaxShortcutCountPerActivity(); method public java.util.List getPinnedShortcuts(); + method public boolean isRateLimitingActive(); method public void removeAllDynamicShortcuts(); method public void removeDynamicShortcuts(java.util.List); method public void reportShortcutUsed(java.lang.String); diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java index f66e1f4a206bd986d8930003e5979b8cc9e437dd..54f1b7672c313ede50e854ab5a0320d30a331df6 100644 --- a/core/java/android/content/pm/ShortcutInfo.java +++ b/core/java/android/content/pm/ShortcutInfo.java @@ -19,6 +19,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.app.TaskStackBuilder; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -919,6 +920,19 @@ public final class ShortcutInfo implements Parcelable { return this; } + /** + * Sets multiple intents instead of a single intent. + * + * @see Builder#setIntent(Intent) + * @see ShortcutInfo#getIntents() + * @see Context#startActivities(Intent[]) + * @see TaskStackBuilder + */ + @NonNull + public Builder setIntents(@NonNull Intent[] intents) { + throw new RuntimeException("NOT SUPPORTED YET"); + } + /** * "Rank" of a shortcut, which is a non-negative value that's used by the launcher app * to sort shortcuts. @@ -1084,7 +1098,7 @@ public final class ShortcutInfo implements Parcelable { } /** - * Return the intent. + * Return the intent. (Or the last intent set with {@link Builder#setIntents(Intent[])}. * *

Launcher applications cannot see the intent. If a {@link ShortcutInfo} is * obtained via {@link LauncherApps}, then this method will always return null. @@ -1103,6 +1117,20 @@ public final class ShortcutInfo implements Parcelable { return intent; } + /** + * Return the intent set with {@link Builder#setIntents(Intent[])}. + * + *

Launcher applications cannot see the intents. If a {@link ShortcutInfo} is + * obtained via {@link LauncherApps}, then this method will always return null. + * Launchers can only start a shortcut intent with {@link LauncherApps#startShortcut}. + * + * @see Builder#setIntents(Intent[]) + */ + @Nullable + public Intent getIntents() { + throw new RuntimeException("NOT SUPPORTED YET"); + } + /** * Return "raw" intent, which is the original intent without the extras. * @hide diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java index f6c0be07db84a7a7f76050825abbc1ca624e0ca9..cfd3442cc07b969a731bfe99bbfba846bc60e835 100644 --- a/core/java/android/content/pm/ShortcutManager.java +++ b/core/java/android/content/pm/ShortcutManager.java @@ -613,6 +613,20 @@ public class ShortcutManager { } } + /** + * Return {@code true} when rate-limiting is active for the caller application. + * + *

See the class level javadoc for details. + */ + public boolean isRateLimitingActive() { + try { + return mService.getRemainingCallCount(mContext.getPackageName(), injectMyUserId()) + == 0; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** * Return the max width for icons, in pixels. */ diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index cff2da9f005c50ed59b85e1d7284809bd053bc59..1913b6116efb12854c295f3a18cb91c461bd1157 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -17,7 +17,6 @@ package com.android.server.pm; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -30,7 +29,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.ILauncherApps; import android.content.pm.IOnAppsChangedListener; import android.content.pm.IPackageManager; -import android.content.pm.LauncherApps; import android.content.pm.LauncherApps.ShortcutQuery; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -461,7 +459,8 @@ public class LauncherAppsService extends SystemService { } // Note the target activity doesn't have to be exported. - prepareIntentForLaunch(intent, sourceBounds); + intent.setSourceBounds(sourceBounds); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); return startShortcutIntentAsPublisher( intent, packageName, startActivityOptions, userId); @@ -521,7 +520,9 @@ public class LauncherAppsService extends SystemService { Intent launchIntent = new Intent(Intent.ACTION_MAIN); launchIntent.addCategory(Intent.CATEGORY_LAUNCHER); - prepareIntentForLaunch(launchIntent, sourceBounds); + launchIntent.setSourceBounds(sourceBounds); + launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK + | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); launchIntent.setPackage(component.getPackageName()); long ident = Binder.clearCallingIdentity(); @@ -562,13 +563,6 @@ public class LauncherAppsService extends SystemService { } } - private void prepareIntentForLaunch(@NonNull Intent launchIntent, - @Nullable Rect sourceBounds) { - launchIntent.setSourceBounds(sourceBounds); - launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK - | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); - } - @Override public void showAppDetailsAsUser(ComponentName component, Rect sourceBounds, Bundle opts, UserHandle user) throws RemoteException { diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java index dc70583c2f8f1ddff97bc8edb6643504277d90ac..efd380bd10fe16b03a7c80de87b5e49e777d529c 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java @@ -1566,12 +1566,22 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE); runWithCaller(CALLING_PACKAGE_1, USER_0, () -> { assertEquals(3, mManager.getRemainingCallCount()); + assertFalse(mManager.isRateLimitingActive()); mManager.setDynamicShortcuts(list(makeShortcut("s"))); + + assertEquals(2, mManager.getRemainingCallCount()); + assertFalse(mManager.isRateLimitingActive()); + mManager.setDynamicShortcuts(list(makeShortcut("s"))); + + assertEquals(1, mManager.getRemainingCallCount()); + assertFalse(mManager.isRateLimitingActive()); + mManager.setDynamicShortcuts(list(makeShortcut("s"))); assertEquals(0, mManager.getRemainingCallCount()); + assertTrue(mManager.isRateLimitingActive()); }); runWithCaller(CALLING_PACKAGE_2, USER_0, () -> { assertEquals(3, mManager.getRemainingCallCount()); @@ -1581,6 +1591,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { mManager.setDynamicShortcuts(list(makeShortcut("s"))); assertEquals(0, mManager.getRemainingCallCount()); + assertTrue(mManager.isRateLimitingActive()); }); runWithCaller(CALLING_PACKAGE_3, USER_0, () -> { MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); @@ -1590,6 +1601,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { mManager.setDynamicShortcuts(list(makeShortcut("s"))); assertEquals(0, mManager.getRemainingCallCount()); + assertTrue(mManager.isRateLimitingActive()); }); runWithCaller(CALLING_PACKAGE_4, USER_0, () -> { MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); @@ -1599,6 +1611,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { mManager.setDynamicShortcuts(list(makeShortcut("s"))); assertEquals(0, mManager.getRemainingCallCount()); + assertTrue(mManager.isRateLimitingActive()); }); runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount()); @@ -1608,6 +1621,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { mManager.setDynamicShortcuts(list(makeShortcut("s"))); assertEquals(0, mManager.getRemainingCallCount()); + assertTrue(mManager.isRateLimitingActive()); }); runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { assertEquals(3, mManager.getRemainingCallCount()); @@ -1617,6 +1631,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { mManager.setDynamicShortcuts(list(makeShortcut("s"))); assertEquals(3, mManager.getRemainingCallCount()); // Still 3! + assertFalse(mManager.isRateLimitingActive()); }); }