Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea11db15 authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Start shortcuts as if publisher apps did using PendingIntent

Bug 29639471

Change-Id: I2aad115669b431cbea785ba92040b1958117ab47
parent 7519df9e
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -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);
}
+1 −1
Original line number Diff line number Diff line
@@ -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,
+27 −0
Original line number Diff line number Diff line
@@ -21664,6 +21664,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 {
+35 −8
Original line number Diff line number Diff line
@@ -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);

            startShortcutIntentAsPublisher(
                    intent, packageName, startActivityOptions, userId);
        }

        @VisibleForTesting
        protected void startShortcutIntentAsPublisher(@NonNull Intent intent,
                @NonNull String publisherPackage, Bundle startActivityOptions, int userId) {

            try {
                final IIntentSender intentSender;

                final long ident = Binder.clearCallingIdentity();
                try {
                mContext.startActivityAsUser(intent, startActivityOptions, UserHandle.of(userId));
                    intentSender = mActivityManagerInternal.getActivityIntentSenderAsPackage(
                            publisherPackage, userId, /* requestCode= */ 0,
                            intent, PendingIntent.FLAG_ONE_SHOT,
                            /* options= */ startActivityOptions);
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            return true;

                // Negative result means a failure.
                ActivityManagerNative.getDefault().sendIntentSender(
                        intentSender, 0, null, null, null, null, null);

            } catch (RemoteException e) {
                return;
            }
        }

        @Override
+12 −0
Original line number Diff line number Diff line
@@ -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.