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

Commit 821d7cd8 authored by Makoto Onuki's avatar Makoto Onuki Committed by Android (Google) Code Review
Browse files

Merge "Implement UNLIMITED_SHORTCUTS_API_CALLS permission."

parents 420f9d07 7d0fa81b
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -490,7 +490,7 @@ class ShortcutPackage extends ShortcutPackageItem {
     * <p>This takes care of the resetting the counter for foreground apps as well as after
     * locale changes.
     */
    public int getApiCallCount() {
    public int getApiCallCount(boolean unlimited) {
        final ShortcutService s = mShortcutUser.mService;

        // Reset the counter if:
@@ -498,8 +498,9 @@ class ShortcutPackage extends ShortcutPackageItem {
        // - the package is *not* in foreground now, but was in foreground at some point
        // since the previous time it had been.
        if (s.isUidForegroundLocked(mPackageUid)
                || mLastKnownForegroundElapsedTime
                    < s.getUidLastForegroundElapsedTimeLocked(mPackageUid)) {
                || (mLastKnownForegroundElapsedTime
                    < s.getUidLastForegroundElapsedTimeLocked(mPackageUid))
                || unlimited) {
            mLastKnownForegroundElapsedTime = s.injectElapsedRealtime();
            resetRateLimiting();
        }
@@ -538,10 +539,10 @@ class ShortcutPackage extends ShortcutPackageItem {
     * <p>This takes care of the resetting the counter for foreground apps as well as after
     * locale changes, which is done internally by {@link #getApiCallCount}.
     */
    public boolean tryApiCall() {
    public boolean tryApiCall(boolean unlimited) {
        final ShortcutService s = mShortcutUser.mService;

        if (getApiCallCount() >= s.mMaxUpdatesPerInterval) {
        if (getApiCallCount(unlimited) >= s.mMaxUpdatesPerInterval) {
            return false;
        }
        mApiCallCount++;
@@ -1248,7 +1249,7 @@ class ShortcutPackage extends ShortcutPackageItem {
        pw.print(prefix);
        pw.print("  ");
        pw.print("Calls: ");
        pw.print(getApiCallCount());
        pw.print(getApiCallCount(/*unlimited=*/ false));
        pw.println();

        // getApiCallCount() may have updated mLastKnownForegroundElapsedTime.
+31 −4
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.server.pm;

import android.Manifest.permission;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -1726,6 +1727,9 @@ public class ShortcutService extends IShortcutService.Stub {
        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
        final int size = newShortcuts.size();

        final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
                injectBinderCallingPid(), injectBinderCallingUid());

        synchronized (mLock) {
            throwIfUserLockedL(userId);

@@ -1738,7 +1742,7 @@ public class ShortcutService extends IShortcutService.Stub {
            ps.enforceShortcutCountsBeforeOperation(newShortcuts, OPERATION_SET);

            // Throttling.
            if (!ps.tryApiCall()) {
            if (!ps.tryApiCall(unlimited)) {
                return false;
            }

@@ -1777,6 +1781,9 @@ public class ShortcutService extends IShortcutService.Stub {
        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
        final int size = newShortcuts.size();

        final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
                injectBinderCallingPid(), injectBinderCallingUid());

        synchronized (mLock) {
            throwIfUserLockedL(userId);

@@ -1790,7 +1797,7 @@ public class ShortcutService extends IShortcutService.Stub {
            ps.enforceShortcutCountsBeforeOperation(newShortcuts, OPERATION_UPDATE);

            // Throttling.
            if (!ps.tryApiCall()) {
            if (!ps.tryApiCall(unlimited)) {
                return false;
            }

@@ -1859,6 +1866,9 @@ public class ShortcutService extends IShortcutService.Stub {
        final List<ShortcutInfo> newShortcuts = (List<ShortcutInfo>) shortcutInfoList.getList();
        final int size = newShortcuts.size();

        final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
                injectBinderCallingPid(), injectBinderCallingUid());

        synchronized (mLock) {
            throwIfUserLockedL(userId);

@@ -1875,7 +1885,7 @@ public class ShortcutService extends IShortcutService.Stub {
            assignImplicitRanks(newShortcuts);

            // Throttling.
            if (!ps.tryApiCall()) {
            if (!ps.tryApiCall(unlimited)) {
                return false;
            }
            for (int i = 0; i < size; i++) {
@@ -2144,11 +2154,14 @@ public class ShortcutService extends IShortcutService.Stub {
    public int getRemainingCallCount(String packageName, @UserIdInt int userId) {
        verifyCaller(packageName, userId);

        final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
                injectBinderCallingPid(), injectBinderCallingUid());

        synchronized (mLock) {
            throwIfUserLockedL(userId);

            final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
            return mMaxUpdatesPerInterval - ps.getApiCallCount();
            return mMaxUpdatesPerInterval - ps.getApiCallCount(unlimited);
        }
    }

@@ -2298,6 +2311,15 @@ public class ShortcutService extends IShortcutService.Stub {
                callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * Returns true if the caller has the "UNLIMITED_SHORTCUTS_API_CALLS" permission.
     */
    @VisibleForTesting
    boolean injectHasUnlimitedShortcutsApiCallsPermission(int callingPid, int callingUid) {
        return mContext.checkPermission(permission.UNLIMITED_SHORTCUTS_API_CALLS,
                callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
    }

    // This method is extracted so we can directly call this method from unit tests,
    // even when hasShortcutPermission() is overridden.
    @VisibleForTesting
@@ -4197,6 +4219,11 @@ public class ShortcutService extends IShortcutService.Stub {
        return getCallingUid();
    }

    @VisibleForTesting
    int injectBinderCallingPid() {
        return getCallingPid();
    }

    private int getCallingUserId() {
        return UserHandle.getUserId(injectBinderCallingUid());
    }
+20 −1
Original line number Diff line number Diff line
@@ -288,6 +288,12 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
            return mInjectedCallingUid;
        }

        @Override
        int injectBinderCallingPid() {
            // Note it's not used in tests, so just return a "random" value.
            return mInjectedCallingUid * 123;
        }

        @Override
        int injectGetPackageUid(String packageName, int userId) {
            return getInjectedPackageInfo(packageName, userId, false).applicationInfo.uid;
@@ -324,6 +330,11 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
            return mDefaultLauncherChecker.test(callingPackage, userId);
        }

        @Override
        boolean injectHasUnlimitedShortcutsApiCallsPermission(int callingPid, int callingUid) {
            return mInjectHasUnlimitedShortcutsApiCallsPermission;
        }

        @Override
        ComponentName getDefaultLauncher(@UserIdInt int userId) {
            final ComponentName activity = mDefaultLauncher.get(userId);
@@ -518,6 +529,12 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
            return mInjectedCallingUid;
        }

        @Override
        int injectBinderCallingPid() {
            // Note it's not used in tests, so just return a "random" value.
            return mInjectedCallingUid * 123;
        }

        @Override
        long injectClearCallingIdentity() {
            final int prevCallingUid = mInjectedCallingUid;
@@ -705,6 +722,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {

    protected boolean mInjectCheckAccessShortcutsPermission = false;

    protected boolean mInjectHasUnlimitedShortcutsApiCallsPermission = false;

    static {
        QUERY_ALL.setQueryFlags(
                ShortcutQuery.FLAG_GET_ALL_KINDS);
@@ -1207,7 +1226,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
    }

    /**
     * This controls {@link ShortcutService#hasShortcutHostPermission(String, int)}, but
     * This controls {@link ShortcutService#hasShortcutHostPermission}, but
     * not {@link ShortcutService#getDefaultLauncher(int)}.  To control the later, use
     * {@link #setDefaultLauncher(int, ComponentName)}.
     */
+32 −1
Original line number Diff line number Diff line
@@ -366,6 +366,37 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
        });
    }

    public void testUnlimitedCalls() {
        setCaller(CALLING_PACKAGE_1, USER_0);

        final ShortcutInfo si1 = makeShortcut("shortcut1");

        assertEquals(3, mManager.getRemainingCallCount());

        assertTrue(mManager.setDynamicShortcuts(list(si1)));
        assertEquals(2, mManager.getRemainingCallCount());

        assertTrue(mManager.addDynamicShortcuts(list(si1)));
        assertEquals(1, mManager.getRemainingCallCount());

        assertTrue(mManager.updateShortcuts(list(si1)));
        assertEquals(0, mManager.getRemainingCallCount());

        // Unlimited now.
        mInjectHasUnlimitedShortcutsApiCallsPermission = true;

        assertEquals(3, mManager.getRemainingCallCount());

        assertTrue(mManager.setDynamicShortcuts(list(si1)));
        assertEquals(3, mManager.getRemainingCallCount());

        assertTrue(mManager.addDynamicShortcuts(list(si1)));
        assertEquals(3, mManager.getRemainingCallCount());

        assertTrue(mManager.updateShortcuts(list(si1)));
        assertEquals(3, mManager.getRemainingCallCount());
    }

   public void testPublishWithNoActivity() {
        // If activity is not explicitly set, use the default one.