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

Commit 4c9fbc50 authored by Mehdi Alizadeh's avatar Mehdi Alizadeh Committed by Android (Google) Code Review
Browse files

Merge "Adds methods in LauncherApps to allow cache/uncache shortcuts"

parents 9fdd1f2e 0de8c29c
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -98,4 +98,9 @@ interface ILauncherApps {
            in ComponentName componentName, int flags, in IShortcutChangeCallback callback,
            in ComponentName componentName, int flags, in IShortcutChangeCallback callback,
            int callbackId);
            int callbackId);
    void unregisterShortcutChangeCallback(String callingPackage, int callbackId);
    void unregisterShortcutChangeCallback(String callingPackage, int callbackId);

    void cacheShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
            in UserHandle user);
    void uncacheShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
            in UserHandle user);
}
}
+56 −0
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
import android.annotation.SystemApi;
@@ -1088,6 +1089,61 @@ public class LauncherApps {
        }
        }
    }
    }


    /**
     * Mark shortcuts as cached for a package.
     *
     * <p>Only dynamic long lived shortcuts can be cached. None dynamic or non long lived shortcuts
     * in the list will be ignored.
     *
     * <p>Unlike pinned shortcuts, where different callers can have different sets of pinned
     * shortcuts, cached state is per shortcut only, and even if multiple callers cache the same
     * shortcut, it can be uncached by any valid caller.
     *
     * @param packageName The target package name.
     * @param shortcutIds The IDs of the shortcut to be cached.
     * @param user The UserHandle of the profile.
     * @throws IllegalStateException when the user is locked, or when the {@code user} user
     * is locked or not running.
     *
     * @see ShortcutManager
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.ACCESS_SHORTCUTS)
    public void cacheShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
            @NonNull UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        try {
            mService.cacheShortcuts(mContext.getPackageName(), packageName, shortcutIds, user);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * Remove cached flag from shortcuts for a package.
     *
     * @param packageName The target package name.
     * @param shortcutIds The IDs of the shortcut to be uncached.
     * @param user The UserHandle of the profile.
     * @throws IllegalStateException when the user is locked, or when the {@code user} user
     * is locked or not running.
     *
     * @see ShortcutManager
     *
     * @hide
     */
    @RequiresPermission(android.Manifest.permission.ACCESS_SHORTCUTS)
    public void uncacheShortcuts(@NonNull String packageName, @NonNull List<String> shortcutIds,
            @NonNull UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        try {
            mService.uncacheShortcuts(mContext.getPackageName(), packageName, shortcutIds, user);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
    /**
     * @hide kept for testing.
     * @hide kept for testing.
     */
     */
+7 −0
Original line number Original line Diff line number Diff line
@@ -85,4 +85,11 @@ public abstract class ShortcutServiceInternal {


    public abstract boolean isForegroundDefaultLauncher(@NonNull String callingPackage,
    public abstract boolean isForegroundDefaultLauncher(@NonNull String callingPackage,
            int callingUid);
            int callingUid);

    public abstract void cacheShortcuts(int launcherUserId,
            @NonNull String callingPackage, @NonNull String packageName,
            @NonNull List<String> shortcutIds, int userId);
    public abstract void uncacheShortcuts(int launcherUserId,
            @NonNull String callingPackage, @NonNull String packageName,
            @NonNull List<String> shortcutIds, int userId);
}
}
+41 −0
Original line number Original line Diff line number Diff line
@@ -661,6 +661,23 @@ public class LauncherAppsService extends SystemService {
            }
            }
        }
        }


        private void ensureStrictAccessShortcutsPermission(@NonNull String callingPackage) {
            verifyCallingPackage(callingPackage);
            if (!injectHasAccessShortcutsPermission(injectBinderCallingPid(),
                    injectBinderCallingUid())) {
                throw new SecurityException("Caller can't access shortcut information");
            }
        }

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

        @Override
        @Override
        public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
        public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
                String packageName, List shortcutIds, List<LocusId> locusIds,
                String packageName, List shortcutIds, List<LocusId> locusIds,
@@ -709,6 +726,30 @@ public class LauncherAppsService extends SystemService {
                    callingPackage, packageName, ids, targetUser.getIdentifier());
                    callingPackage, packageName, ids, targetUser.getIdentifier());
        }
        }


        @Override
        public void cacheShortcuts(String callingPackage, String packageName, List<String> ids,
                UserHandle targetUser) {
            ensureStrictAccessShortcutsPermission(callingPackage);
            if (!canAccessProfile(targetUser.getIdentifier(), "Cannot cache shortcuts")) {
                return;
            }

            mShortcutServiceInternal.cacheShortcuts(getCallingUserId(),
                    callingPackage, packageName, ids, targetUser.getIdentifier());
        }

        @Override
        public void uncacheShortcuts(String callingPackage, String packageName, List<String> ids,
                UserHandle targetUser) {
            ensureStrictAccessShortcutsPermission(callingPackage);
            if (!canAccessProfile(targetUser.getIdentifier(), "Cannot uncache shortcuts")) {
                return;
            }

            mShortcutServiceInternal.uncacheShortcuts(getCallingUserId(),
                    callingPackage, packageName, ids, targetUser.getIdentifier());
        }

        @Override
        @Override
        public int getShortcutIconResId(String callingPackage, String packageName, String id,
        public int getShortcutIconResId(String callingPackage, String packageName, String id,
                int targetUserId) {
                int targetUserId) {
+63 −1
Original line number Original line Diff line number Diff line
@@ -1704,7 +1704,7 @@ public class ShortcutService extends IShortcutService.Stub {
            ShortcutInfo.validateIcon(shortcut.getIcon());
            ShortcutInfo.validateIcon(shortcut.getIcon());
        }
        }


        shortcut.replaceFlags(0);
        shortcut.replaceFlags(shortcut.getFlags() & ShortcutInfo.FLAG_LONG_LIVED);
    }
    }


    private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate) {
    private void fixUpIncomingShortcutInfo(@NonNull ShortcutInfo shortcut, boolean forUpdate) {
@@ -2757,6 +2757,68 @@ public class ShortcutService extends IShortcutService.Stub {
            verifyStates();
            verifyStates();
        }
        }


        @Override
        public void cacheShortcuts(int launcherUserId,
                @NonNull String callingPackage, @NonNull String packageName,
                @NonNull List<String> shortcutIds, int userId) {
            updateCachedShortcutsInternal(launcherUserId, callingPackage, packageName, shortcutIds,
                    userId, /* doCache= */ true);
        }

        @Override
        public void uncacheShortcuts(int launcherUserId,
                @NonNull String callingPackage, @NonNull String packageName,
                @NonNull List<String> shortcutIds, int userId) {
            updateCachedShortcutsInternal(launcherUserId, callingPackage, packageName, shortcutIds,
                    userId, /* doCache= */ false);
        }

        private void updateCachedShortcutsInternal(int launcherUserId,
                @NonNull String callingPackage, @NonNull String packageName,
                @NonNull List<String> shortcutIds, int userId, boolean doCache) {
            // Calling permission must be checked by LauncherAppsImpl.
            Preconditions.checkStringNotEmpty(packageName, "packageName");
            Objects.requireNonNull(shortcutIds, "shortcutIds");

            synchronized (mLock) {
                throwIfUserLockedL(userId);
                throwIfUserLockedL(launcherUserId);

                final int idSize = shortcutIds.size();
                final ShortcutPackage sp = getUserShortcutsLocked(userId)
                        .getPackageShortcutsIfExists(packageName);
                if (idSize == 0 || sp == null) {
                    return;
                }

                for (int i = 0; i < idSize; i++) {
                    final String id = Preconditions.checkStringNotEmpty(shortcutIds.get(i));
                    final ShortcutInfo si = sp.findShortcutById(id);
                    if (si == null || doCache == si.isCached()) {
                        continue;
                    }

                    if (doCache) {
                        if (si.isDynamic() && si.isLongLived()) {
                            si.addFlags(ShortcutInfo.FLAG_CACHED);
                        } else {
                            Log.w(TAG, "Only dynamic long lived shortcuts can get cached. Ignoring"
                                    + "shortcut " + si.getId());
                        }
                    } else {
                        if (si.isDynamic()) {
                            si.clearFlags(ShortcutInfo.FLAG_CACHED);
                        } else {
                            sp.deleteLongLivedWithId(id, /*ignoreInvisible=*/ true);
                        }
                    }
                }
            }
            packageShortcutsChanged(packageName, userId);

            verifyStates();
        }

        @Override
        @Override
        public Intent[] createShortcutIntents(int launcherUserId,
        public Intent[] createShortcutIntents(int launcherUserId,
                @NonNull String callingPackage,
                @NonNull String callingPackage,
Loading