Include LauncherApps#getShortcutIntents

Add new api to retrieve pending intents from specified shortcut.

Bug: 151359749
CTS-Coverage-Bug: 13975407
Test: atest ShortcutManagerTest12
Change-Id: I6c413615d1392805f601561550dcb85bfe242b37
This commit is contained in:
Pinyao Ting
2021-03-22 16:41:42 -07:00
parent f41fa968d8
commit 4750fe5036
6 changed files with 106 additions and 0 deletions

View File

@@ -12131,6 +12131,7 @@ package android.content.pm {
method @Nullable public android.content.IntentSender getShortcutConfigActivityIntent(@NonNull android.content.pm.LauncherActivityInfo);
method public java.util.List<android.content.pm.LauncherActivityInfo> getShortcutConfigActivityList(@Nullable String, @NonNull android.os.UserHandle);
method public android.graphics.drawable.Drawable getShortcutIconDrawable(@NonNull android.content.pm.ShortcutInfo, int);
method @Nullable public android.app.PendingIntent getShortcutIntent(@NonNull String, @NonNull String, @Nullable android.os.Bundle, @NonNull android.os.UserHandle);
method @Nullable public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(@NonNull android.content.pm.LauncherApps.ShortcutQuery, @NonNull android.os.UserHandle);
method @Nullable public android.os.Bundle getSuspendedPackageLauncherExtras(String, android.os.UserHandle);
method public boolean hasShortcutHostPermission();

View File

@@ -90,6 +90,8 @@ interface ILauncherApps {
String callingPackage, String packageName, in UserHandle user);
IntentSender getShortcutConfigActivityIntent(String callingPackage, in ComponentName component,
in UserHandle user);
PendingIntent getShortcutIntent(String callingPackage, String packageName, String shortcutId,
in Bundle opts, in UserHandle user);
// Unregister is performed using package installer
void registerPackageInstallerCallback(String callingPackage,

View File

@@ -842,6 +842,30 @@ public class LauncherApps {
}
}
/**
* Returns PendingIntent associated with specified shortcut.
*
* @param packageName The packageName of the shortcut
* @param shortcutId The id of the shortcut
* @param opts Options to pass to the PendingIntent
* @param user The UserHandle of the profile
*/
@Nullable
public PendingIntent getShortcutIntent(@NonNull final String packageName,
@NonNull final String shortcutId, @Nullable final Bundle opts,
@NonNull final UserHandle user) {
logErrorForInvalidProfileAccess(user);
if (DEBUG) {
Log.i(TAG, "GetShortcutIntent " + packageName + "/" + shortcutId + " " + user);
}
try {
return mService.getShortcutIntent(
mContext.getPackageName(), packageName, shortcutId, opts, user);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
* Retrieves a list of config activities for creating {@link ShortcutInfo}.
*

View File

@@ -18,6 +18,7 @@ package com.android.server.pm;
import static android.app.ActivityOptions.KEY_SPLASH_SCREEN_THEME;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.app.PendingIntent.FLAG_MUTABLE;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.pm.LauncherApps.FLAG_CACHE_BUBBLE_SHORTCUTS;
@@ -648,6 +649,43 @@ public class LauncherAppsService extends SystemService {
}
}
/**
* Returns the intents for a specific shortcut.
*/
@Nullable
@Override
public PendingIntent getShortcutIntent(@NonNull final String callingPackage,
@NonNull final String packageName, @NonNull final String shortcutId,
@Nullable final Bundle opts, @NonNull final UserHandle user)
throws RemoteException {
Objects.requireNonNull(callingPackage);
Objects.requireNonNull(packageName);
Objects.requireNonNull(shortcutId);
Objects.requireNonNull(user);
ensureShortcutPermission(callingPackage);
if (!canAccessProfile(user.getIdentifier(), "Cannot get shortcuts")) {
return null;
}
final Intent[] intents = mShortcutServiceInternal.createShortcutIntents(
getCallingUserId(), callingPackage, packageName, shortcutId,
user.getIdentifier(), injectBinderCallingPid(), injectBinderCallingUid());
if (intents == null || intents.length == 0) {
return null;
}
final long ident = Binder.clearCallingIdentity();
try {
return injectCreatePendingIntent(mContext.createPackageContextAsUser(packageName,
0, user), 0 /* requestCode */, intents, FLAG_MUTABLE, opts, user);
} catch (PackageManager.NameNotFoundException e) {
Slog.e(TAG, "Cannot create pending intent from shortcut " + shortcutId, e);
} finally {
Binder.restoreCallingIdentity(ident);
}
return null;
}
@Override
public boolean isPackageEnabled(String callingPackage, String packageName, UserHandle user)
throws RemoteException {
@@ -756,6 +794,13 @@ public class LauncherAppsService extends SystemService {
callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
}
@VisibleForTesting
PendingIntent injectCreatePendingIntent(Context context, int requestCode,
@NonNull Intent[] intents, int flags, Bundle options, UserHandle user) {
return PendingIntent.getActivitiesAsUser(context, requestCode, intents, flags, options,
user);
}
@Override
public ParceledListSlice getShortcuts(@NonNull final String callingPackage,
@NonNull final ShortcutQueryWrapper query, @NonNull final UserHandle targetUser) {

View File

@@ -43,6 +43,7 @@ import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.IUidObserver;
import android.app.PendingIntent;
import android.app.Person;
import android.app.admin.DevicePolicyManager;
import android.app.appsearch.AppSearchBatchResult;
@@ -60,6 +61,7 @@ import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
@@ -196,6 +198,13 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
return this;
}
@Override
public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
throws PackageManager.NameNotFoundException {
// ignore.
return this;
}
@Override
public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
IntentFilter filter, String broadcastPermission, Handler scheduler) {
@@ -619,6 +628,12 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
boolean injectHasInteractAcrossUsersFullPermission(int callingPid, int callingUid) {
return false;
}
@Override
PendingIntent injectCreatePendingIntent(Context context, int requestCode,
@NonNull Intent[] intents, int flags, Bundle options, UserHandle user) {
return new PendingIntent(mock(IIntentSender.class));
}
}
protected class LauncherAppsTestable extends LauncherApps {

View File

@@ -15,8 +15,13 @@
*/
package com.android.server.pm;
import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
import android.app.PendingIntent;
import android.app.appsearch.PackageIdentifier;
import android.content.pm.AppSearchShortcutInfo;
import android.os.RemoteException;
import android.os.UserHandle;
import java.util.Random;
@@ -41,4 +46,18 @@ public class ShortcutManagerTest12 extends BaseShortcutManagerTest {
new PackageIdentifier(CALLING_PACKAGE_2, cert)));
});
}
public void testGetShortcutIntents_ReturnsMutablePendingIntents() throws RemoteException {
setDefaultLauncher(USER_0, LAUNCHER_1);
runWithCaller(CALLING_PACKAGE_1, USER_0, () ->
assertTrue(mManager.setDynamicShortcuts(list(makeShortcut("s1"))))
);
runWithCaller(LAUNCHER_1, USER_0, () -> {
final PendingIntent intent = mLauncherApps.getShortcutIntent(
CALLING_PACKAGE_1, "s1", null, UserHandle.SYSTEM);
assertNotNull(intent);
});
}
}