Loading core/java/android/content/pm/LauncherApps.java +7 −0 Original line number Diff line number Diff line Loading @@ -1185,6 +1185,13 @@ public class LauncherApps { * Represents a "pin shortcut" request made by an app, which is sent with * an {@link #ACTION_CONFIRM_PIN_ITEM} intent to the default launcher app. * * <p>Note the launcher may receive a request to pin a shortcut that is already pinned, because * the user may actually want to have multiple icons of the same shortcut on the launcher. * The launcher can tell this case by calling {@link ShortcutInfo#isPinned()} on the shortcut * returned by {@link #getShortcutInfo()}. In this case, calling {@link #accept()} is optional; * even if the launcher does not call it, the shortcut is already pinned. Also in this case, * the {@code options} argument to {@link #accept(Bundle)} will be ignored. * * @see #EXTRA_PIN_ITEM_REQUEST * @see #getPinItemRequest(Intent) */ Loading services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java +27 −28 Original line number Diff line number Diff line Loading @@ -203,19 +203,13 @@ class ShortcutRequestPinProcessor { // Next, validate the incoming shortcut, etc. final PinItemRequest request; if (inShortcut != null) { request = requestPinShortcutLocked(inShortcut, resultIntent, confirmActivity, true /* ignoreIfAlreadyPinned */); request = requestPinShortcutLocked(inShortcut, resultIntent, confirmActivity); } else { int launcherUid = mService.injectGetPackageUid( confirmActivity.first.getPackageName(), launcherUserId); request = new PinItemRequest(inAppWidget, new PinItemRequestInner(this, resultIntent, launcherUid)); } if (request == null) { sendResultIntent(resultIntent, null); return true; } return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request); } Loading @@ -238,23 +232,17 @@ class ShortcutRequestPinProcessor { mService.throwIfUserLockedL(launcherUserId); // Next, validate the incoming shortcut, etc. PinItemRequest request = requestPinShortcutLocked(inShortcut, null, Pair.create(defaultLauncher, launcherUserId), false /* ignoreIfAlreadyPinned */); if (request == null) { return null; } final PinItemRequest request = requestPinShortcutLocked(inShortcut, null, Pair.create(defaultLauncher, launcherUserId)); return new Intent().putExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST, request); } /** * Handle {@link android.content.pm.ShortcutManager#requestPinShortcut)}. * * @param ignoreIfAlreadyPinned if true and the {@param inShortcut} is already pinned for * {@param confirmActivity}, null is returned instead. */ @NonNull private PinItemRequest requestPinShortcutLocked(ShortcutInfo inShortcut, IntentSender resultIntent, Pair<ComponentName, Integer> confirmActivity, boolean ignoreIfAlreadyPinned) { IntentSender resultIntentOriginal, Pair<ComponentName, Integer> confirmActivity) { final ShortcutPackage ps = mService.getPackageShortcutsForPublisherLocked( inShortcut.getPackage(), inShortcut.getUserId()); Loading @@ -272,16 +260,20 @@ class ShortcutRequestPinProcessor { final String launcherPackage = confirmActivity.first.getPackageName(); final int launcherUserId = confirmActivity.second; IntentSender resultIntentToSend = resultIntentOriginal; if (existsAlready) { validateExistingShortcut(existing); final boolean isAlreadyPinned = mService.getLauncherShortcutsLocked( launcherPackage, existing.getUserId(), launcherUserId).hasPinned(existing); // See if it's already pinned. if (ignoreIfAlreadyPinned && isAlreadyPinned) { Log.i(TAG, "Launcher's already pinning shortcut " + existing.getId() + " for package " + existing.getPackage()); return null; if (isAlreadyPinned) { // When the shortcut is already pinned by this launcher, the request will always // succeed, so just send the result at this point. sendResultIntent(resultIntentOriginal, null); // So, do not send the intent again. resultIntentToSend = null; } // Pass a clone, not the original. Loading @@ -289,7 +281,7 @@ class ShortcutRequestPinProcessor { shortcutForLauncher = existing.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER); if (!isAlreadyPinned) { // FLAG_PINNED is still set, if it's pinned by other launchers. // FLAG_PINNED may still be set, if it's pinned by other launchers. shortcutForLauncher.clearFlags(ShortcutInfo.FLAG_PINNED); } } else { Loading Loading @@ -320,8 +312,8 @@ class ShortcutRequestPinProcessor { // Create a request object. final PinShortcutRequestInner inner = new PinShortcutRequestInner(this, inShortcut, shortcutForLauncher, resultIntent, launcherPackage, launcherUserId, new PinShortcutRequestInner(this, inShortcut, shortcutForLauncher, resultIntentToSend, launcherPackage, launcherUserId, mService.injectGetPackageUid(launcherPackage, launcherUserId), existsAlready); Loading Loading @@ -410,6 +402,16 @@ class ShortcutRequestPinProcessor { return false; } final ShortcutLauncher launcher = mService.getLauncherShortcutsLocked( launcherPackage, appUserId, launcherUserId); launcher.attemptToRestoreIfNeededAndSave(); if (launcher.hasPinned(original)) { if (DEBUG) { Slog.d(TAG, "Shortcut " + original + " already pinned."); } return true; } final ShortcutPackage ps = mService.getPackageShortcutsForPublisherLocked( appPackageName, appUserId); final ShortcutInfo current = ps.findShortcutById(shortcutId); Loading Loading @@ -447,9 +449,6 @@ class ShortcutRequestPinProcessor { Slog.d(TAG, "Pinning " + shortcutId); } final ShortcutLauncher launcher = mService.getLauncherShortcutsLocked( launcherPackage, appUserId, launcherUserId); launcher.attemptToRestoreIfNeededAndSave(); launcher.addPinnedShortcut(appPackageName, appUserId, shortcutId); if (current == null) { Loading services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java +132 −15 Original line number Diff line number Diff line Loading @@ -22,6 +22,9 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; import static org.mockito.Matchers.notNull; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; Loading Loading @@ -238,7 +241,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { * - Launcher supports the feature. * - Shortcut doesn't pre-exist. */ private void checkRequestPinShortcut(@Nullable PendingIntent resultIntent) { private void checkRequestPinShortcut(@Nullable IntentSender resultIntent) { setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0)); setDefaultLauncher(USER_10, mMainActivityFetcher.apply(LAUNCHER_2, USER_10)); Loading @@ -254,8 +257,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { assertNull(s.getActivity()); assertTrue(mManager.requestPinShortcut(s, resultIntent == null ? null : resultIntent.getIntentSender())); assertTrue(mManager.requestPinShortcut(s, resultIntent)); verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class)); Loading Loading @@ -294,9 +296,9 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { // This method is always called, even with PI == null. if (resultIntent == null) { verify(mServiceContext, times(1)).sendIntentSender(eq(null)); verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); } else { verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class)); verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); } runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { Loading @@ -314,11 +316,12 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { checkRequestPinShortcut(/* resultIntent=*/ null); } public void testRequestPinShortcut_withCallback() { final PendingIntent resultIntent = PendingIntent.getActivity(getTestContext(), 0, new Intent(), 0); private IntentSender makeResultIntent() { return PendingIntent.getActivity(getTestContext(), 0, new Intent(), 0).getIntentSender(); } checkRequestPinShortcut(resultIntent); public void testRequestPinShortcut_withCallback() { checkRequestPinShortcut(makeResultIntent()); } public void testRequestPinShortcut_explicitTargetActivity() { Loading Loading @@ -578,8 +581,15 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { public void testRequestPinShortcut_dynamicExists_alreadyPinned() { setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0)); final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32); runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1")))); final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, "s1") .setShortLabel("Title-" + "s1") .setIcon(res32x32) .setIntent(makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class)); final ShortcutInfo s = b.build(); assertTrue(mManager.setDynamicShortcuts(list(s))); }); runWithCaller(LAUNCHER_1, USER_0, () -> { Loading @@ -590,14 +600,66 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { assertWith(getCallerShortcuts()) .haveIds("s1") .areAllDynamic() .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main")) .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) .areAllPinned(); assertTrue(mManager.requestPinShortcut(makeShortcutIdOnly("s1"), /* resultIntent=*/ null)); makeResultIntent())); // The intent should be sent right away. verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class)); verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); }); // Already pinned. runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { assertWith(getCallerShortcuts()) .haveIds("s1") .areAllDynamic() .areAllEnabled() .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) .areAllPinned(); }); // ... But the launcher will still receive the request. runWithCaller(LAUNCHER_1, USER_0, () -> { // Check the intent passed to startActivityAsUser(). final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0)); assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage); // Check the request object. final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue()); assertPinItemRequest(request); assertWith(request.getShortcutInfo()) .haveIds("s1") .areAllDynamic() .areAllPinned() // Note it's pinned already. .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) .areAllWithNoIntent(); assertAllHaveIcon(list(request.getShortcutInfo())); reset(mServiceContext); // Accept the request. assertTrue(request.accept()); // The intent is only sent once, so times(1). verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); }); // Still pinned. runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { assertWith(getCallerShortcuts()) .haveIds("s1") .areAllDynamic() .areAllEnabled() .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) .areAllPinned(); }); } Loading @@ -621,10 +683,65 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { .areAllPinned(); assertTrue(mManager.requestPinShortcut(makeShortcutIdOnly("ms1"), /* resultIntent=*/ null)); makeResultIntent())); // The intent should be sent right away. verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class)); verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); }); // Already pinned. runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1") .areAllManifest() .areAllEnabled() .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName())) .areAllPinned(); }); // ... But the launcher will still receive the request. runWithCaller(LAUNCHER_1, USER_0, () -> { // Check the intent passed to startActivityAsUser(). final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0)); assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage); // Check the request object. final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue()); assertPinItemRequest(request); assertWith(request.getShortcutInfo()) .haveIds("ms1") .areAllManifest() .areAllPinned() // Note it's pinned already. .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName())) .areAllWithNoIntent(); assertAllHaveIcon(list(request.getShortcutInfo())); reset(mServiceContext); // Accept the request. assertTrue(request.accept()); // The intent is only sent once, so times(1). verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); }); // Still pinned. runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1") .areAllManifest() .areAllEnabled() .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName())) .areAllPinned(); }); } Loading Loading
core/java/android/content/pm/LauncherApps.java +7 −0 Original line number Diff line number Diff line Loading @@ -1185,6 +1185,13 @@ public class LauncherApps { * Represents a "pin shortcut" request made by an app, which is sent with * an {@link #ACTION_CONFIRM_PIN_ITEM} intent to the default launcher app. * * <p>Note the launcher may receive a request to pin a shortcut that is already pinned, because * the user may actually want to have multiple icons of the same shortcut on the launcher. * The launcher can tell this case by calling {@link ShortcutInfo#isPinned()} on the shortcut * returned by {@link #getShortcutInfo()}. In this case, calling {@link #accept()} is optional; * even if the launcher does not call it, the shortcut is already pinned. Also in this case, * the {@code options} argument to {@link #accept(Bundle)} will be ignored. * * @see #EXTRA_PIN_ITEM_REQUEST * @see #getPinItemRequest(Intent) */ Loading
services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java +27 −28 Original line number Diff line number Diff line Loading @@ -203,19 +203,13 @@ class ShortcutRequestPinProcessor { // Next, validate the incoming shortcut, etc. final PinItemRequest request; if (inShortcut != null) { request = requestPinShortcutLocked(inShortcut, resultIntent, confirmActivity, true /* ignoreIfAlreadyPinned */); request = requestPinShortcutLocked(inShortcut, resultIntent, confirmActivity); } else { int launcherUid = mService.injectGetPackageUid( confirmActivity.first.getPackageName(), launcherUserId); request = new PinItemRequest(inAppWidget, new PinItemRequestInner(this, resultIntent, launcherUid)); } if (request == null) { sendResultIntent(resultIntent, null); return true; } return startRequestConfirmActivity(confirmActivity.first, launcherUserId, request); } Loading @@ -238,23 +232,17 @@ class ShortcutRequestPinProcessor { mService.throwIfUserLockedL(launcherUserId); // Next, validate the incoming shortcut, etc. PinItemRequest request = requestPinShortcutLocked(inShortcut, null, Pair.create(defaultLauncher, launcherUserId), false /* ignoreIfAlreadyPinned */); if (request == null) { return null; } final PinItemRequest request = requestPinShortcutLocked(inShortcut, null, Pair.create(defaultLauncher, launcherUserId)); return new Intent().putExtra(LauncherApps.EXTRA_PIN_ITEM_REQUEST, request); } /** * Handle {@link android.content.pm.ShortcutManager#requestPinShortcut)}. * * @param ignoreIfAlreadyPinned if true and the {@param inShortcut} is already pinned for * {@param confirmActivity}, null is returned instead. */ @NonNull private PinItemRequest requestPinShortcutLocked(ShortcutInfo inShortcut, IntentSender resultIntent, Pair<ComponentName, Integer> confirmActivity, boolean ignoreIfAlreadyPinned) { IntentSender resultIntentOriginal, Pair<ComponentName, Integer> confirmActivity) { final ShortcutPackage ps = mService.getPackageShortcutsForPublisherLocked( inShortcut.getPackage(), inShortcut.getUserId()); Loading @@ -272,16 +260,20 @@ class ShortcutRequestPinProcessor { final String launcherPackage = confirmActivity.first.getPackageName(); final int launcherUserId = confirmActivity.second; IntentSender resultIntentToSend = resultIntentOriginal; if (existsAlready) { validateExistingShortcut(existing); final boolean isAlreadyPinned = mService.getLauncherShortcutsLocked( launcherPackage, existing.getUserId(), launcherUserId).hasPinned(existing); // See if it's already pinned. if (ignoreIfAlreadyPinned && isAlreadyPinned) { Log.i(TAG, "Launcher's already pinning shortcut " + existing.getId() + " for package " + existing.getPackage()); return null; if (isAlreadyPinned) { // When the shortcut is already pinned by this launcher, the request will always // succeed, so just send the result at this point. sendResultIntent(resultIntentOriginal, null); // So, do not send the intent again. resultIntentToSend = null; } // Pass a clone, not the original. Loading @@ -289,7 +281,7 @@ class ShortcutRequestPinProcessor { shortcutForLauncher = existing.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER); if (!isAlreadyPinned) { // FLAG_PINNED is still set, if it's pinned by other launchers. // FLAG_PINNED may still be set, if it's pinned by other launchers. shortcutForLauncher.clearFlags(ShortcutInfo.FLAG_PINNED); } } else { Loading Loading @@ -320,8 +312,8 @@ class ShortcutRequestPinProcessor { // Create a request object. final PinShortcutRequestInner inner = new PinShortcutRequestInner(this, inShortcut, shortcutForLauncher, resultIntent, launcherPackage, launcherUserId, new PinShortcutRequestInner(this, inShortcut, shortcutForLauncher, resultIntentToSend, launcherPackage, launcherUserId, mService.injectGetPackageUid(launcherPackage, launcherUserId), existsAlready); Loading Loading @@ -410,6 +402,16 @@ class ShortcutRequestPinProcessor { return false; } final ShortcutLauncher launcher = mService.getLauncherShortcutsLocked( launcherPackage, appUserId, launcherUserId); launcher.attemptToRestoreIfNeededAndSave(); if (launcher.hasPinned(original)) { if (DEBUG) { Slog.d(TAG, "Shortcut " + original + " already pinned."); } return true; } final ShortcutPackage ps = mService.getPackageShortcutsForPublisherLocked( appPackageName, appUserId); final ShortcutInfo current = ps.findShortcutById(shortcutId); Loading Loading @@ -447,9 +449,6 @@ class ShortcutRequestPinProcessor { Slog.d(TAG, "Pinning " + shortcutId); } final ShortcutLauncher launcher = mService.getLauncherShortcutsLocked( launcherPackage, appUserId, launcherUserId); launcher.attemptToRestoreIfNeededAndSave(); launcher.addPinnedShortcut(appPackageName, appUserId, shortcutId); if (current == null) { Loading
services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java +132 −15 Original line number Diff line number Diff line Loading @@ -22,6 +22,9 @@ import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isNull; import static org.mockito.Matchers.notNull; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; Loading Loading @@ -238,7 +241,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { * - Launcher supports the feature. * - Shortcut doesn't pre-exist. */ private void checkRequestPinShortcut(@Nullable PendingIntent resultIntent) { private void checkRequestPinShortcut(@Nullable IntentSender resultIntent) { setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0)); setDefaultLauncher(USER_10, mMainActivityFetcher.apply(LAUNCHER_2, USER_10)); Loading @@ -254,8 +257,7 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { assertNull(s.getActivity()); assertTrue(mManager.requestPinShortcut(s, resultIntent == null ? null : resultIntent.getIntentSender())); assertTrue(mManager.requestPinShortcut(s, resultIntent)); verify(mServiceContext, times(0)).sendIntentSender(any(IntentSender.class)); Loading Loading @@ -294,9 +296,9 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { // This method is always called, even with PI == null. if (resultIntent == null) { verify(mServiceContext, times(1)).sendIntentSender(eq(null)); verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); } else { verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class)); verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); } runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { Loading @@ -314,11 +316,12 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { checkRequestPinShortcut(/* resultIntent=*/ null); } public void testRequestPinShortcut_withCallback() { final PendingIntent resultIntent = PendingIntent.getActivity(getTestContext(), 0, new Intent(), 0); private IntentSender makeResultIntent() { return PendingIntent.getActivity(getTestContext(), 0, new Intent(), 0).getIntentSender(); } checkRequestPinShortcut(resultIntent); public void testRequestPinShortcut_withCallback() { checkRequestPinShortcut(makeResultIntent()); } public void testRequestPinShortcut_explicitTargetActivity() { Loading Loading @@ -578,8 +581,15 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { public void testRequestPinShortcut_dynamicExists_alreadyPinned() { setDefaultLauncher(USER_0, mMainActivityFetcher.apply(LAUNCHER_1, USER_0)); final Icon res32x32 = Icon.createWithResource(getTestContext(), R.drawable.black_32x32); runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1")))); final ShortcutInfo.Builder b = new ShortcutInfo.Builder(mClientContext, "s1") .setShortLabel("Title-" + "s1") .setIcon(res32x32) .setIntent(makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class)); final ShortcutInfo s = b.build(); assertTrue(mManager.setDynamicShortcuts(list(s))); }); runWithCaller(LAUNCHER_1, USER_0, () -> { Loading @@ -590,14 +600,66 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { assertWith(getCallerShortcuts()) .haveIds("s1") .areAllDynamic() .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "main")) .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) .areAllPinned(); assertTrue(mManager.requestPinShortcut(makeShortcutIdOnly("s1"), /* resultIntent=*/ null)); makeResultIntent())); // The intent should be sent right away. verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class)); verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); }); // Already pinned. runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { assertWith(getCallerShortcuts()) .haveIds("s1") .areAllDynamic() .areAllEnabled() .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) .areAllPinned(); }); // ... But the launcher will still receive the request. runWithCaller(LAUNCHER_1, USER_0, () -> { // Check the intent passed to startActivityAsUser(). final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0)); assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage); // Check the request object. final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue()); assertPinItemRequest(request); assertWith(request.getShortcutInfo()) .haveIds("s1") .areAllDynamic() .areAllPinned() // Note it's pinned already. .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) .areAllWithNoIntent(); assertAllHaveIcon(list(request.getShortcutInfo())); reset(mServiceContext); // Accept the request. assertTrue(request.accept()); // The intent is only sent once, so times(1). verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); }); // Still pinned. runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { assertWith(getCallerShortcuts()) .haveIds("s1") .areAllDynamic() .areAllEnabled() .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, "MainActivity")) .areAllPinned(); }); } Loading @@ -621,10 +683,65 @@ public class ShortcutManagerTest8 extends BaseShortcutManagerTest { .areAllPinned(); assertTrue(mManager.requestPinShortcut(makeShortcutIdOnly("ms1"), /* resultIntent=*/ null)); makeResultIntent())); // The intent should be sent right away. verify(mServiceContext, times(1)).sendIntentSender(any(IntentSender.class)); verify(mServiceContext, times(1)).sendIntentSender(notNull(IntentSender.class)); }); // Already pinned. runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1") .areAllManifest() .areAllEnabled() .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName())) .areAllPinned(); }); // ... But the launcher will still receive the request. runWithCaller(LAUNCHER_1, USER_0, () -> { // Check the intent passed to startActivityAsUser(). final ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class); verify(mServiceContext).startActivityAsUser(intent.capture(), eq(HANDLE_USER_0)); assertPinItemRequestIntent(intent.getValue(), mInjectedClientPackage); // Check the request object. final PinItemRequest request = mLauncherApps.getPinItemRequest(intent.getValue()); assertPinItemRequest(request); assertWith(request.getShortcutInfo()) .haveIds("ms1") .areAllManifest() .areAllPinned() // Note it's pinned already. .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName())) .areAllWithNoIntent(); assertAllHaveIcon(list(request.getShortcutInfo())); reset(mServiceContext); // Accept the request. assertTrue(request.accept()); // The intent is only sent once, so times(1). verify(mServiceContext, times(1)).sendIntentSender(isNull(IntentSender.class)); }); // Still pinned. runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> { assertWith(getCallerShortcuts()) .haveIds("ms1") .areAllManifest() .areAllEnabled() .areAllWithActivity(new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName())) .areAllPinned(); }); } Loading