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

Commit 3bf75714 authored by Mehdi Alizadeh's avatar Mehdi Alizadeh Committed by Automerger Merge Worker
Browse files

Merge "Adds unit tests for ShortcutChangeCallback APIs" into rvc-dev am: 082d0c47

Change-Id: I7279314ae42551780706c8f1d56c7579ffeb2986
parents 3381f111 082d0c47
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -507,7 +507,8 @@ public class LauncherApps {
        /**
         * Indicates that one or more shortcuts, that match the {@link ShortcutQuery} used to
         * register this callback, have been added or updated.
         * @see LauncherApps#registerShortcutChangeCallback(ShortcutChangeCallback, ShortcutQuery)
         * @see LauncherApps#registerShortcutChangeCallback(ShortcutChangeCallback, ShortcutQuery,
         * Executor)
         *
         * <p>Only the applications that are allowed to access the shortcut information,
         * as defined in {@link #hasShortcutHostPermission()}, will receive it.
@@ -525,7 +526,8 @@ public class LauncherApps {
        /**
         * Indicates that one or more shortcuts, that match the {@link ShortcutQuery} used to
         * register this callback, have been removed.
         * @see LauncherApps#registerShortcutChangeCallback(ShortcutChangeCallback, ShortcutQuery)
         * @see LauncherApps#registerShortcutChangeCallback(ShortcutChangeCallback, ShortcutQuery,
         * Executor)
         *
         * <p>Only the applications that are allowed to access the shortcut information,
         * as defined in {@link #hasShortcutHostPermission()}, will receive it.
+29 −53
Original line number Diff line number Diff line
@@ -746,9 +746,8 @@ public class LauncherAppsService extends SystemService {
            }

            UserHandle user = UserHandle.of(injectCallingUserId());
            if (mContext.checkCallingOrSelfPermission(
                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
                    == PackageManager.PERMISSION_GRANTED) {
            if (injectHasInteractAcrossUsersFullPermission(injectBinderCallingPid(),
                    injectBinderCallingUid())) {
                user = null;
            }

@@ -1053,29 +1052,6 @@ public class LauncherAppsService extends SystemService {
        }

        public static class ShortcutChangeHandler implements LauncherApps.ShortcutChangeCallback {

            static class QueryInfo {
                final long mChangedSince;
                final String mPackage;
                final List<String> mShortcutIds;
                final List<LocusId> mLocusIds;
                final ComponentName mActivity;
                final int mQueryFlags;
                final UserHandle mCallbackUser;

                QueryInfo(long changedSince, String packageName, List<String> shortcutIds,
                        List<LocusId> locusIds, ComponentName activity, int flags,
                        UserHandle callbackUser) {
                    mChangedSince = changedSince;
                    mPackage = packageName;
                    mShortcutIds = shortcutIds;
                    mLocusIds = locusIds;
                    mActivity = activity;
                    mQueryFlags = flags;
                    mCallbackUser = callbackUser;
                }
            }

            private final UserManagerInternal mUserManagerInternal;

            ShortcutChangeHandler(UserManagerInternal userManager) {
@@ -1088,9 +1064,7 @@ public class LauncherAppsService extends SystemService {
            public synchronized void addShortcutChangeCallback(IShortcutChangeCallback callback,
                    ShortcutQueryWrapper query, UserHandle user) {
                mCallbacks.unregister(callback);
                mCallbacks.register(callback, new QueryInfo(query.getChangedSince(),
                        query.getPackage(), query.getShortcutIds(), query.getLocusIds(),
                        query.getActivity(), query.getQueryFlags(), user));
                mCallbacks.register(callback, new Pair<>(query, user));
            }

            public synchronized void removeShortcutChangeCallback(
@@ -1116,16 +1090,19 @@ public class LauncherAppsService extends SystemService {

                for (int i = 0; i < count; i++) {
                    final IShortcutChangeCallback callback = mCallbacks.getBroadcastItem(i);
                    final QueryInfo query = (QueryInfo) mCallbacks.getBroadcastCookie(i);
                    final Pair<ShortcutQueryWrapper, UserHandle> cookie =
                            (Pair<ShortcutQueryWrapper, UserHandle>)
                                    mCallbacks.getBroadcastCookie(i);

                    if (query.mCallbackUser != null && !hasUserAccess(query.mCallbackUser, user)) {
                    final UserHandle callbackUser = cookie.second;
                    if (callbackUser != null && !hasUserAccess(callbackUser, user)) {
                        // Callback owner does not have access to the shortcuts' user.
                        continue;
                    }

                    // Filter the list by query, if any matches exists, send via callback.
                    List<ShortcutInfo> matchedList =
                            filterShortcutsByQuery(packageName, shortcuts, query);
                    List<ShortcutInfo> matchedList = filterShortcutsByQuery(packageName, shortcuts,
                            cookie.first, shortcutsRemoved);
                    if (!CollectionUtils.isEmpty(matchedList)) {
                        try {
                            if (shortcutsRemoved) {
@@ -1143,21 +1120,25 @@ public class LauncherAppsService extends SystemService {
            }

            public static List<ShortcutInfo> filterShortcutsByQuery(String packageName,
                    List<ShortcutInfo> shortcuts, QueryInfo query) {
                if (query.mPackage != null && query.mPackage != packageName) {
                    List<ShortcutInfo> shortcuts, ShortcutQueryWrapper query,
                    boolean shortcutsRemoved) {
                final long changedSince = query.getChangedSince();
                final String queryPackage = query.getPackage();
                final List<String> shortcutIds = query.getShortcutIds();
                final List<LocusId> locusIds = query.getLocusIds();
                final ComponentName activity = query.getActivity();
                final int flags = query.getQueryFlags();

                if (queryPackage != null && !queryPackage.equals(packageName)) {
                    return null;
                }

                List<ShortcutInfo> matches = new ArrayList<>();

                final boolean matchDynamic =
                        (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_DYNAMIC) != 0;
                final boolean matchPinned =
                        (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_PINNED) != 0;
                final boolean matchManifest =
                        (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_MANIFEST) != 0;
                final boolean matchCached =
                        (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_CACHED) != 0;
                final boolean matchDynamic = (flags & ShortcutQuery.FLAG_MATCH_DYNAMIC) != 0;
                final boolean matchPinned = (flags & ShortcutQuery.FLAG_MATCH_PINNED) != 0;
                final boolean matchManifest = (flags & ShortcutQuery.FLAG_MATCH_MANIFEST) != 0;
                final boolean matchCached = (flags & ShortcutQuery.FLAG_MATCH_CACHED) != 0;
                final int shortcutFlags = (matchDynamic ? ShortcutInfo.FLAG_DYNAMIC : 0)
                        | (matchPinned ? ShortcutInfo.FLAG_PINNED : 0)
                        | (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0)
@@ -1166,24 +1147,19 @@ public class LauncherAppsService extends SystemService {
                for (int i = 0; i < shortcuts.size(); i++) {
                    final ShortcutInfo si = shortcuts.get(i);

                    if (query.mActivity != null && !query.mActivity.equals(si.getActivity())) {
                    if (activity != null && !activity.equals(si.getActivity())) {
                        continue;
                    }

                    if (query.mChangedSince != 0
                            && query.mChangedSince > si.getLastChangedTimestamp()) {
                    if (changedSince != 0 && changedSince > si.getLastChangedTimestamp()) {
                        continue;
                    }

                    if (query.mShortcutIds != null && !query.mShortcutIds.contains(si.getId())) {
                    if (shortcutIds != null && !shortcutIds.contains(si.getId())) {
                        continue;
                    }

                    if (query.mLocusIds != null && !query.mLocusIds.contains(si.getLocusId())) {
                    if (locusIds != null && !locusIds.contains(si.getLocusId())) {
                        continue;
                    }

                    if ((shortcutFlags & si.getFlags()) != 0) {
                    if (shortcutsRemoved || (shortcutFlags & si.getFlags()) != 0) {
                        matches.add(si);
                    }
                }
+63 −37
Original line number Diff line number Diff line
@@ -256,7 +256,7 @@ class ShortcutPackage extends ShortcutPackageItem {
        if (shortcut != null) {
            mShortcutUser.mService.removeIconLocked(shortcut);
            shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED
                    | ShortcutInfo.FLAG_MANIFEST);
                    | ShortcutInfo.FLAG_MANIFEST | ShortcutInfo.FLAG_CACHED);
        }
        return shortcut;
    }
@@ -281,8 +281,10 @@ class ShortcutPackage extends ShortcutPackageItem {
     * invisible.
     *
     * It checks the max number of dynamic shortcuts.
     *
     * @return True if it replaced an existing shortcut, False otherwise.
     */
    public void addOrReplaceDynamicShortcut(@NonNull ShortcutInfo newShortcut) {
    public boolean addOrReplaceDynamicShortcut(@NonNull ShortcutInfo newShortcut) {

        Preconditions.checkArgument(newShortcut.isEnabled(),
                "add/setDynamicShortcuts() cannot publish disabled shortcuts");
@@ -291,38 +293,59 @@ class ShortcutPackage extends ShortcutPackageItem {

        final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());

        final boolean replaced;

        final boolean wasPinned;
        final boolean wasCached;

        if (oldShortcut == null) {
            replaced = false;
            wasPinned = false;
            wasCached = false;
        } else {
            // It's an update case.
            // Make sure the target is updatable. (i.e. should be mutable.)
            oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
            replaced = true;

            wasPinned = oldShortcut.isPinned();
            wasCached = oldShortcut.isCached();
        }

        // If it was originally pinned, the new one should be pinned too.
        if (wasPinned) {
            newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
        }
        if (wasCached) {
            newShortcut.addFlags(ShortcutInfo.FLAG_CACHED);
        }

        forceReplaceShortcutInner(newShortcut);
        return replaced;
    }

    /**
     * Push a shortcut. If the max number of dynamic shortcuts is already reached, remove the
     * shortcut with the lowest rank before adding the new shortcut.
     *
     * Any shortcut that gets altered (removed or changed) as a result of this push operation will
     * be included and returned in changedShortcuts.
     *
     * @return True if a shortcut had to be removed to complete this operation, False otherwise.
     */
    public boolean pushDynamicShortcut(@NonNull ShortcutInfo newShortcut) {
    public boolean pushDynamicShortcut(@NonNull ShortcutInfo newShortcut,
            @NonNull List<ShortcutInfo> changedShortcuts) {
        Preconditions.checkArgument(newShortcut.isEnabled(),
                "pushDynamicShortcuts() cannot publish disabled shortcuts");

        newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);

        changedShortcuts.clear();
        final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
        boolean wasPinned = false;
        boolean wasCached = false;

        boolean deleted = false;

        if (oldShortcut == null) {
            final ShortcutService service = mShortcutUser.mService;
@@ -343,10 +366,11 @@ class ShortcutPackage extends ShortcutPackageItem {
                    // All shortcuts are manifest shortcuts and cannot be removed.
                    Slog.e(TAG, "Failed to remove manifest shortcut while pushing dynamic shortcut "
                            + newShortcut.getId());
                    return false;
                    return true;  // poppedShortcuts is empty which indicates a failure.
                }

                deleteDynamicWithId(shortcut.getId(), /*ignoreInvisible=*/ true);
                changedShortcuts.add(shortcut);
                deleted = deleteDynamicWithId(shortcut.getId(), /*ignoreInvisible=*/ true) != null;
            }
        } else {
            // It's an update case.
@@ -354,15 +378,19 @@ class ShortcutPackage extends ShortcutPackageItem {
            oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);

            wasPinned = oldShortcut.isPinned();
            wasCached = oldShortcut.isCached();
        }

        // If it was originally pinned, the new one should be pinned too.
        // If it was originally pinned or cached, the new one should be pinned or cached too.
        if (wasPinned) {
            newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
        }
        if (wasCached) {
            newShortcut.addFlags(ShortcutInfo.FLAG_CACHED);
        }

        forceReplaceShortcutInner(newShortcut);
        return true;
        return deleted;
    }

    /**
@@ -371,8 +399,7 @@ class ShortcutPackage extends ShortcutPackageItem {
     * @return List of removed shortcuts.
     */
    private List<ShortcutInfo> removeOrphans() {
        ArrayList<String> removeList = null; // Lazily initialize.
        List<ShortcutInfo> removedShortcuts = null;
        List<ShortcutInfo> removeList = null;

        for (int i = mShortcuts.size() - 1; i >= 0; i--) {
            final ShortcutInfo si = mShortcuts.valueAt(i);
@@ -381,18 +408,16 @@ class ShortcutPackage extends ShortcutPackageItem {

            if (removeList == null) {
                removeList = new ArrayList<>();
                removedShortcuts = new ArrayList<>();
            }
            removeList.add(si.getId());
            removedShortcuts.add(si);
            removeList.add(si);
        }
        if (removeList != null) {
            for (int i = removeList.size() - 1; i >= 0; i--) {
                forceDeleteShortcutInner(removeList.get(i));
                forceDeleteShortcutInner(removeList.get(i).getId());
            }
        }

        return removedShortcuts;
        return removeList;
    }

    /**
@@ -424,68 +449,69 @@ class ShortcutPackage extends ShortcutPackageItem {
     * Remove a dynamic shortcut by ID.  It'll be removed from the dynamic set, but if the shortcut
     * is pinned or cached, it'll remain as a pinned or cached shortcut, and is still enabled.
     *
     * @return true if it's removed, or false if it was not actually removed because it is either
     * @return The deleted shortcut, or null if it was not actually removed because it is either
     * pinned or cached.
     */
    public boolean deleteDynamicWithId(@NonNull String shortcutId, boolean ignoreInvisible) {
        final ShortcutInfo removed = deleteOrDisableWithId(
    public ShortcutInfo deleteDynamicWithId(@NonNull String shortcutId, boolean ignoreInvisible) {
        return deleteOrDisableWithId(
                shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false, ignoreInvisible,
                ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
        return removed == null;
    }

    /**
     * Disable a dynamic shortcut by ID. It'll be removed from the dynamic set, but if the shortcut
     * is pinned, it'll remain as a pinned shortcut, but will be disabled.
     *
     * @return true if it's actually removed because it wasn't pinned, or false if it's still
     * pinned.
     * @return Shortcut if the disabled shortcut got removed because it wasn't pinned. Or null if
     * it's still pinned.
     */
    private boolean disableDynamicWithId(@NonNull String shortcutId, boolean ignoreInvisible,
    private ShortcutInfo disableDynamicWithId(@NonNull String shortcutId, boolean ignoreInvisible,
            int disabledReason) {
        final ShortcutInfo disabled = deleteOrDisableWithId(
                shortcutId, /* disable =*/ true, /* overrideImmutable=*/ false, ignoreInvisible,
                disabledReason);
        return disabled == null;
        return deleteOrDisableWithId(shortcutId, /* disable =*/ true, /* overrideImmutable=*/ false,
                ignoreInvisible, disabledReason);
    }

    /**
     * Remove a long lived shortcut by ID. If the shortcut is pinned, it'll remain as a pinned
     * shortcut, and is still enabled.
     *
     * @return true if it's actually removed because it wasn't pinned, or false if it's still
     * pinned.
     * @return The deleted shortcut, or null if it was not actually removed because it's pinned.
     */
    public boolean deleteLongLivedWithId(@NonNull String shortcutId, boolean ignoreInvisible) {
    public ShortcutInfo deleteLongLivedWithId(@NonNull String shortcutId, boolean ignoreInvisible) {
        final ShortcutInfo shortcut = mShortcuts.get(shortcutId);
        if (shortcut != null) {
            shortcut.clearFlags(ShortcutInfo.FLAG_CACHED);
        }
        final ShortcutInfo removed = deleteOrDisableWithId(
        return deleteOrDisableWithId(
                shortcutId, /* disable =*/ false, /* overrideImmutable=*/ false, ignoreInvisible,
                ShortcutInfo.DISABLED_REASON_NOT_DISABLED);
        return removed == null;
    }

    /**
     * Disable a dynamic shortcut by ID.  It'll be removed from the dynamic set, but if the shortcut
     * is pinned, it'll remain as a pinned shortcut but will be disabled.
     *
     * @return Shortcut if the disabled shortcut got removed because it wasn't pinned. Or null if
     * it's still pinned.
     */
    public void disableWithId(@NonNull String shortcutId, String disabledMessage,
    public ShortcutInfo disableWithId(@NonNull String shortcutId, String disabledMessage,
            int disabledMessageResId, boolean overrideImmutable, boolean ignoreInvisible,
            int disabledReason) {
        final ShortcutInfo disabled = deleteOrDisableWithId(shortcutId, /* disable =*/ true,
        final ShortcutInfo deleted = deleteOrDisableWithId(shortcutId, /* disable =*/ true,
                overrideImmutable, ignoreInvisible, disabledReason);

        // If disabled id still exists, it is pinned and we need to update the disabled message.
        final ShortcutInfo disabled = mShortcuts.get(shortcutId);
        if (disabled != null) {
            if (disabledMessage != null) {
                disabled.setDisabledMessage(disabledMessage);
            } else if (disabledMessageResId != 0) {
                disabled.setDisabledMessageResId(disabledMessageResId);

                mShortcutUser.mService.fixUpShortcutResourceNamesAndValues(disabled);
            }
        }

        return deleted;
    }

    @Nullable
@@ -521,10 +547,10 @@ class ShortcutPackage extends ShortcutPackageItem {
                oldShortcut.setActivity(null);
            }

            return oldShortcut;
            return null;
        } else {
            forceDeleteShortcutInner(shortcutId);
            return null;
            return oldShortcut;
        }
    }

@@ -1005,7 +1031,7 @@ class ShortcutPackage extends ShortcutPackageItem {
                                "%s is no longer main activity. Disabling shorcut %s.",
                                getPackageName(), si.getId()));
                        if (disableDynamicWithId(si.getId(), /*ignoreInvisible*/ false,
                                ShortcutInfo.DISABLED_REASON_APP_CHANGED)) {
                                ShortcutInfo.DISABLED_REASON_APP_CHANGED) != null) {
                            continue; // Actually removed.
                        }
                        // Still pinned, so fall-through and possibly update the resources.
+3 −5
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
@@ -513,10 +513,6 @@ class ShortcutRequestPinProcessor {

            launcher.addPinnedShortcut(appPackageName, appUserId, shortcutId,
                    /*forPinRequest=*/ true);
            if (changedShortcuts == null) {
                changedShortcuts = new ArrayList<>(1);
            }
            changedShortcuts.add(original);

            if (current == null) {
                if (DEBUG) {
@@ -526,6 +522,8 @@ class ShortcutRequestPinProcessor {
            }

            ps.adjustRanks(); // Shouldn't be needed, but just in case.

            changedShortcuts = Collections.singletonList(ps.findShortcutById(shortcutId));
        }

        mService.verifyStates();
+193 −69

File changed.

Preview size limit exceeded, changes collapsed.

Loading