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

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

ShortcutManagre: foreground check, more tests.

Test: Manual test and all the unit tests:
adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest1 -w com.android.frameworks.servicestests
... to test8

Bug 32908854

Change-Id: I30ba421e9730741776c1936e40ccf7b7431289da
parent ab99c11c
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -128,6 +128,10 @@ public final class ShortcutInfo implements Parcelable {
    public static final int CLONE_REMOVE_FOR_LAUNCHER = CLONE_REMOVE_ICON | CLONE_REMOVE_INTENT
            | CLONE_REMOVE_RES_NAMES;

    /** @hide */
    public static final int CLONE_REMOVE_FOR_LAUNCHER_APPROVAL = CLONE_REMOVE_INTENT
            | CLONE_REMOVE_RES_NAMES;

    /** @hide */
    @IntDef(flag = true,
            value = {
+28 −15
Original line number Diff line number Diff line
@@ -48,7 +48,15 @@ class ShortcutRequestPinProcessor {
     */
    private static class PinShortcutRequestInner extends IPinItemRequest.Stub {
        private final ShortcutRequestPinProcessor mProcessor;
        public final ShortcutInfo shortcut;
        /** Original shortcut passed by the app. */
        public final ShortcutInfo shortcutOriginal;

        /**
         * Cloned shortcut that's passed to the launcher.  The notable difference from
         * {@link #shortcutOriginal} is it must not have the intent.
         */
        public final ShortcutInfo shortcutForLauncher;

        private final IntentSender mResultIntent;

        public final String launcherPackage;
@@ -59,10 +67,12 @@ class ShortcutRequestPinProcessor {
        private boolean mAccepted;

        private PinShortcutRequestInner(ShortcutRequestPinProcessor processor,
                ShortcutInfo shortcut, IntentSender resultIntent,
                ShortcutInfo shortcutOriginal, ShortcutInfo shortcutForLauncher,
                IntentSender resultIntent,
                String launcherPackage, int launcherUserId, boolean preExisting) {
            mProcessor = processor;
            this.shortcut = shortcut;
            this.shortcutOriginal = shortcutOriginal;
            this.shortcutForLauncher = shortcutForLauncher;
            mResultIntent = resultIntent;
            this.launcherPackage = launcherPackage;
            this.launcherUserId = launcherUserId;
@@ -99,8 +109,8 @@ class ShortcutRequestPinProcessor {
                mAccepted = true;
            }
            if (DEBUG) {
                Slog.d(TAG, "Launcher accepted shortcut. ID=" + shortcut.getId()
                        + " package=" + shortcut.getPackage()
                Slog.d(TAG, "Launcher accepted shortcut. ID=" + shortcutOriginal.getId()
                        + " package=" + shortcutOriginal.getPackage()
                        + " options=" + options);
            }

@@ -163,7 +173,7 @@ class ShortcutRequestPinProcessor {
        }

        // This is the shortcut that'll be sent to the launcher.
        final ShortcutInfo shortcutToSend;
        final ShortcutInfo shortcutForLauncher;

        if (existsAlready) {
            validateExistingShortcut(existing);
@@ -179,8 +189,10 @@ class ShortcutRequestPinProcessor {

            // Pass a clone, not the original.
            // Note this will remove the intent and icons.
            shortcutToSend = existing.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
            shortcutToSend.clearFlags(ShortcutInfo.FLAG_PINNED);
            shortcutForLauncher = existing.clone(ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);

            // FLAG_PINNED is still set, if it's pinned by other launchers.
            shortcutForLauncher.clearFlags(ShortcutInfo.FLAG_PINNED);
        } else {
            // It doesn't exist, so it must have all mandatory fields.
            mService.validateShortcutForPinRequest(inShortcut);
@@ -191,17 +203,18 @@ class ShortcutRequestPinProcessor {
            if (DEBUG) {
                Slog.d(TAG, "resolved shortcut=" + inShortcut.toInsecureString());
            }
            // TODO Remove the intent here -- don't pass shortcut intents to the launcher.
            shortcutToSend = inShortcut;
            // We should strip out the intent, but should preserve the icon.
            shortcutForLauncher = inShortcut.clone(
                    ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER_APPROVAL);
        }

        // Create a request object.
        final PinShortcutRequestInner inner =
                new PinShortcutRequestInner(this, shortcutToSend, resultIntent,
                new PinShortcutRequestInner(this, inShortcut, shortcutForLauncher, resultIntent,
                        launcherPackage, launcherUserId, existsAlready);

        final PinItemRequest outer = new PinItemRequest(PinItemRequest.REQUEST_TYPE_SHORTCUT,
                shortcutToSend, inner);
                shortcutForLauncher, inner);

        return startRequestConfirmActivity(launcherComponent, launcherUserId, outer);
    }
@@ -210,7 +223,7 @@ class ShortcutRequestPinProcessor {
        // Make sure it's enabled.
        // (Because we can't always force enable it automatically as it may be a stale
        // manifest shortcut.)
        Preconditions.checkState(shortcutInfo.isEnabled(),
        Preconditions.checkArgument(shortcutInfo.isEnabled(),
                "Shortcut ID=" + shortcutInfo + " already exists but disabled.");

    }
@@ -270,7 +283,7 @@ class ShortcutRequestPinProcessor {
     */
    public boolean directPinShortcut(PinShortcutRequestInner request) {

        final ShortcutInfo original = request.shortcut;
        final ShortcutInfo original = request.shortcutOriginal;
        final int appUserId = original.getUserId();
        final String appPackageName = original.getPackage();
        final int launcherUserId = request.launcherUserId;
@@ -292,7 +305,7 @@ class ShortcutRequestPinProcessor {
            try {
                if (current == null) {
                    // It doesn't exist, so it must have all necessary fields.
                    mService.validateShortcutForPinRequest(request.shortcut);
                    mService.validateShortcutForPinRequest(original);
                } else {
                    validateExistingShortcut(current);
                }
+3 −2
Original line number Diff line number Diff line
@@ -1865,9 +1865,10 @@ public class ShortcutService extends IShortcutService.Stub {
        synchronized (mLock) {
            throwIfUserLockedL(userId);

            // TODO Make sure the caller is in the foreground.
            Preconditions.checkState(isUidForegroundLocked(injectBinderCallingUid()),
                    "Calling application must have a foreground activity or a foreground service");

            // TODO Cancel all pending request from the same app.
            // TODO Cancel all pending requests from the caller.

            // Send request to the launcher, if supported.
            ret = mShortcutRequestPinProcessor.requestPinShortcutLocked(shortcut, resultIntent);
+51 −1
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.test.InstrumentationTestCase;
@@ -1288,6 +1289,13 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
                + "/" + ShortcutService.FILENAME_USER_PACKAGES, message);
    }

    /**
     * Make a shortcut with an ID only.
     */
    protected ShortcutInfo makeShortcutIdOnly(String id) {
        return new ShortcutInfo.Builder(mClientContext, id).build();
    }

    /**
     * Make a shortcut with an ID.
     */
@@ -1297,12 +1305,19 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
    }

    @Deprecated // Title was renamed to short label.
    protected ShortcutInfo makeShortcutWithTitle(String id, String title) {
        return makeShortcut(
                id, title, /* activity =*/ null, /* icon =*/ null,
                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
    }

    protected ShortcutInfo makeShortcutWithShortLabel(String id, String shortLabel) {
        return makeShortcut(
                id, shortLabel, /* activity =*/ null, /* icon =*/ null,
                makeIntent(Intent.ACTION_VIEW, ShortcutActivity.class), /* rank =*/ 0);
    }

    /**
     * Make a shortcut with an ID and timestamp.
     */
@@ -1695,6 +1710,13 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
        return getLauncherShortcuts(launcher, userId, ShortcutQuery.FLAG_GET_PINNED);
    }

    protected List<ShortcutInfo> getShortcutAsLauncher(int targetUserId) {
        final ShortcutQuery q = new ShortcutQuery();
        q.setQueryFlags(ShortcutQuery.FLAG_MATCH_DYNAMIC | ShortcutQuery.FLAG_MATCH_DYNAMIC
                | ShortcutQuery.FLAG_MATCH_PINNED);
        return mLauncherApps.getShortcuts(q, UserHandle.of(targetUserId));
    }

    protected ShortcutInfo getShortcutInfoAsLauncher(String packageName, String shortcutId,
            int userId) {
        final List<ShortcutInfo> infoList =
@@ -1968,7 +1990,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
    public static List<ShortcutInfo> assertAllHaveIcon(
            List<ShortcutInfo> actualShortcuts) {
        for (ShortcutInfo s : actualShortcuts) {
            assertTrue("ID " + s.getId() + " has no icon ", s.hasIconFile() || s.hasIconResource());
            assertTrue("ID " + s.getId() + " has no icon ",
                    s.hasIconFile() || s.hasIconResource() || s.getIcon() != null);
        }
        return actualShortcuts;
    }
@@ -2030,4 +2053,31 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
        return ri(PACKAGE_FALLBACK_LAUNCHER, PACKAGE_FALLBACK_LAUNCHER_NAME, true,
                PACKAGE_FALLBACK_LAUNCHER_PRIORITY);
    }

    protected void makeCallerForeground() {
        try {
            mService.mUidObserver.onUidStateChanged(
                    mInjectedCallingUid, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
        } catch (RemoteException e) {
            e.rethrowAsRuntimeException();
        }
    }

    protected void makeCallerBackground() {
        try {
            mService.mUidObserver.onUidStateChanged(
                    mInjectedCallingUid, ActivityManager.PROCESS_STATE_TOP_SLEEPING);
        } catch (RemoteException e) {
            e.rethrowAsRuntimeException();
        }
    }

    protected void publishManifestShortcutsAsCaller(int resId) {
        addManifestShortcutResource(
                new ComponentName(getCallingPackage(), ShortcutActivity.class.getName()),
                resId);
        updatePackageVersion(getCallingPackage(), 1);
        mService.mPackageMonitor.onReceive(getTestContext(),
                genPackageAddIntent(getCallingPackage(), getCallingUserId()));
    }
}
Loading