diff options
5 files changed, 84 insertions, 9 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 33ae553fb57f..6dd14fd263e3 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -19,7 +19,9 @@ package android.app; 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 class ActivityManagerInternal { */ 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 430c7e706b64..c19e6382775a 100644 --- a/core/java/android/content/pm/ILauncherApps.aidl +++ b/core/java/android/content/pm/ILauncherApps.aidl @@ -51,7 +51,7 @@ interface ILauncherApps { 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 ae9492fd3b22..e5579e29c208 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 @@ public final class ActivityManagerService extends ActivityManagerNative 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 46da60764e7e..03d5645f7e5d 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 @@ package com.android.server.pm; 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 @@ public class LauncherAppsService extends SystemService { 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 @@ public class LauncherAppsService extends SystemService { 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 @@ public class LauncherAppsService extends SystemService { } @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 @@ public class LauncherAppsService extends SystemService { 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 7cf03af23d05..b6084d5a1387 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.Nullable; 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 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { 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 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { 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 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { 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. |