Merge "Start shortcuts as if publisher apps did using PendingIntent" into nyc-mr1-dev
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 33ae553..6dd14fd 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -19,7 +19,9 @@
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.IIntentSender;
+import android.content.Intent;
import android.content.res.Configuration;
+import android.os.Bundle;
import android.os.IBinder;
import android.service.voice.IVoiceInteractionSession;
@@ -161,4 +163,11 @@
*/
public abstract void updatePersistentConfigurationForUser(@NonNull Configuration values,
int userId);
+
+ /**
+ * Create an {@link IIntentSender} to start an activity, as if {@code packageName} on
+ * user {@code userId} created it.
+ */
+ public abstract IIntentSender getActivityIntentSenderAsPackage(String packageName,
+ int userId, int requestCode, Intent intent, int flags, Bundle bOptions);
}
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 430c7e7..c19e638 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -51,7 +51,7 @@
in List shortcutIds, in ComponentName componentName, int flags, in UserHandle user);
void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
in UserHandle user);
- boolean startShortcut(String callingPackage, String packageName, String id,
+ void startShortcut(String callingPackage, String packageName, String id,
in Rect sourceBounds, in Bundle startActivityOptions, int userId);
int getShortcutIconResId(String callingPackage, String packageName, String id,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index ae9492f..e5579e2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -21724,6 +21724,33 @@
updateConfigurationLocked(values, null, false, true, userId);
}
}
+
+ @Override
+ public IIntentSender getActivityIntentSenderAsPackage(
+ String packageName, int userId, int requestCode, Intent intent,
+ int flags, Bundle bOptions) {
+ String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
+ mContext.getContentResolver()) : null;
+
+ // UID of the package on user userId.
+ // "= 0" is needed because otherwise catch(RemoteException) would make it look like
+ // packageUid may not be initialized.
+ int packageUid = 0;
+ try {
+ packageUid = AppGlobals.getPackageManager().getPackageUid(
+ packageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
+ } catch (RemoteException e) {
+ // Shouldn't happen.
+ }
+
+ synchronized (ActivityManagerService.this) {
+ return getIntentSenderLocked(
+ ActivityManager.INTENT_SENDER_ACTIVITY, packageName, packageUid,
+ UserHandle.getUserId(packageUid), /*token*/ null, /*resultWho*/ null,
+ requestCode, new Intent[] {intent}, new String[]{resolvedType},
+ flags, bOptions);
+ }
+ }
}
private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 46da607..03d5645f 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -19,9 +19,13 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.ActivityManagerInternal;
+import android.app.ActivityManagerNative;
import android.app.AppGlobals;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
+import android.content.IIntentSender;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -98,6 +102,7 @@
private final Context mContext;
private final PackageManager mPm;
private final UserManager mUm;
+ private final ActivityManagerInternal mActivityManagerInternal;
private final ShortcutServiceInternal mShortcutServiceInternal;
private final PackageCallbackList<IOnAppsChangedListener> mListeners
= new PackageCallbackList<IOnAppsChangedListener>();
@@ -110,6 +115,8 @@
mContext = context;
mPm = mContext.getPackageManager();
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mActivityManagerInternal = Preconditions.checkNotNull(
+ LocalServices.getService(ActivityManagerInternal.class));
mShortcutServiceInternal = Preconditions.checkNotNull(
LocalServices.getService(ShortcutServiceInternal.class));
mShortcutServiceInternal.addListener(mPackageMonitor);
@@ -432,7 +439,7 @@
}
@Override
- public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
+ public void startShortcut(String callingPackage, String packageName, String shortcutId,
Rect sourceBounds, Bundle startActivityOptions, int userId) {
verifyCallingPackage(callingPackage);
ensureInUserProfiles(userId, "Cannot start activity for unrelated profile " + userId);
@@ -451,20 +458,40 @@
final Intent intent = mShortcutServiceInternal.createShortcutIntent(getCallingUserId(),
callingPackage, packageName, shortcutId, userId);
if (intent == null) {
- return false;
+ return;
}
// Note the target activity doesn't have to be exported.
- intent.setSourceBounds(sourceBounds);
prepareIntentForLaunch(intent, sourceBounds);
- final long ident = Binder.clearCallingIdentity();
+ startShortcutIntentAsPublisher(
+ intent, packageName, startActivityOptions, userId);
+ }
+
+ @VisibleForTesting
+ protected void startShortcutIntentAsPublisher(@NonNull Intent intent,
+ @NonNull String publisherPackage, Bundle startActivityOptions, int userId) {
+
try {
- mContext.startActivityAsUser(intent, startActivityOptions, UserHandle.of(userId));
- } finally {
- Binder.restoreCallingIdentity(ident);
+ final IIntentSender intentSender;
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ intentSender = mActivityManagerInternal.getActivityIntentSenderAsPackage(
+ publisherPackage, userId, /* requestCode= */ 0,
+ intent, PendingIntent.FLAG_ONE_SHOT,
+ /* options= */ startActivityOptions);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
+ // Negative result means a failure.
+ ActivityManagerNative.getDefault().sendIntentSender(
+ intentSender, 0, null, null, null, null, null);
+
+ } catch (RemoteException e) {
+ return;
}
- return true;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 7cf03af..b6084d5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -37,6 +37,7 @@
import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.Activity;
+import android.app.ActivityManagerInternal;
import android.app.IUidObserver;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
@@ -466,6 +467,13 @@
void injectRestoreCallingIdentity(long token) {
mInjectedCallingUid = (int) token;
}
+
+ @Override
+ protected void startShortcutIntentAsPublisher(@NonNull Intent intent,
+ @NonNull String publisherPackage, Bundle startActivityOptions, int userId) {
+ // Just forward to startActivityAsUser() during unit tests.
+ mContext.startActivityAsUser(intent, startActivityOptions, UserHandle.of(userId));
+ }
}
protected class LauncherAppsTestable extends LauncherApps {
@@ -518,6 +526,7 @@
protected PackageManagerInternal mMockPackageManagerInternal;
protected UserManager mMockUserManager;
protected UsageStatsManagerInternal mMockUsageStatsManagerInternal;
+ protected ActivityManagerInternal mMockActivityManagerInternal;
protected static final String CALLING_PACKAGE_1 = "com.android.test.1";
protected static final int CALLING_UID_1 = 10001;
@@ -616,11 +625,14 @@
mMockPackageManagerInternal = mock(PackageManagerInternal.class);
mMockUserManager = mock(UserManager.class);
mMockUsageStatsManagerInternal = mock(UsageStatsManagerInternal.class);
+ mMockActivityManagerInternal = mock(ActivityManagerInternal.class);
LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
LocalServices.addService(UsageStatsManagerInternal.class, mMockUsageStatsManagerInternal);
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ LocalServices.addService(ActivityManagerInternal.class, mMockActivityManagerInternal);
// Prepare injection values.