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

Commit efa662ec authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Integrate LauncherApps API with AppSearch"

parents 521d2e9f 24912ef3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2918,6 +2918,7 @@ package android.content.pm {
  }
  public static class LauncherApps.ShortcutQuery {
    field public static final int FLAG_GET_PERSISTED_DATA = 4096; // 0x1000
    field @RequiresPermission(android.Manifest.permission.ACCESS_SHORTCUTS) public static final int FLAG_GET_PERSONS_DATA = 2048; // 0x800
  }
+4 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.os.ParcelFileDescriptor;

import com.android.internal.infra.AndroidFuture;

import java.util.List;

/**
@@ -73,6 +75,8 @@ interface ILauncherApps {

    ParceledListSlice getShortcuts(String callingPackage, in ShortcutQueryWrapper query,
            in UserHandle user);
    void getShortcutsAsync(String callingPackage, in ShortcutQueryWrapper query,
            in UserHandle user, in AndroidFuture<List<ShortcutInfo>> cb);
    void pinShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
            in UserHandle user);
    boolean startShortcut(String callingPackage, String packageName, String featureId, String id,
+35 −2
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ import android.util.Log;
import android.util.Pair;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.function.pooled.PooledLambda;

import java.io.FileNotFoundException;
@@ -84,6 +85,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;

/**
@@ -439,6 +441,17 @@ public class LauncherApps {
         */
        public static final int FLAG_GET_KEY_FIELDS_ONLY = 1 << 2;

        /**
         * Includes shortcuts from persistence layer in the search result.
         *
         * <p>The caller should make the query on a worker thread since accessing persistence layer
         * is considered asynchronous.
         *
         * @hide
         */
        @SystemApi
        public static final int FLAG_GET_PERSISTED_DATA = 1 << 12;

        /**
         * Populate the persons field in the result. See {@link ShortcutInfo#getPersons()}.
         *
@@ -459,6 +472,7 @@ public class LauncherApps {
                FLAG_MATCH_PINNED_BY_ANY_LAUNCHER,
                FLAG_GET_KEY_FIELDS_ONLY,
                FLAG_GET_PERSONS_DATA,
                FLAG_GET_PERSISTED_DATA
        })
        @Retention(RetentionPolicy.SOURCE)
        public @interface QueryFlags {}
@@ -1137,6 +1151,9 @@ public class LauncherApps {
            @NonNull UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        try {
            if ((query.mQueryFlags & ShortcutQuery.FLAG_GET_PERSISTED_DATA) != 0) {
                return getShortcutsBlocked(query, user);
            }
            // Note this is the only case we need to update the disabled message for shortcuts
            // that weren't restored.
            // The restore problem messages are only shown by the user, and publishers will never
@@ -1151,6 +1168,22 @@ public class LauncherApps {
        }
    }

    private List<ShortcutInfo> getShortcutsBlocked(@NonNull ShortcutQuery query,
            @NonNull UserHandle user) {
        logErrorForInvalidProfileAccess(user);
        final AndroidFuture<List<ShortcutInfo>> future = new AndroidFuture<>();
        future.thenApply(this::maybeUpdateDisabledMessage);
        try {
            mService.getShortcutsAsync(mContext.getPackageName(),
                            new ShortcutQueryWrapper(query), user, future);
            return future.get();
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @hide // No longer used.  Use getShortcuts() instead.  Kept for unit tests.
     */
+38 −0
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@ import android.content.pm.LauncherApps.ShortcutQuery;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;

import com.android.internal.infra.AndroidFuture;

import java.util.List;

/**
@@ -50,6 +52,19 @@ public abstract class ShortcutServiceInternal {
            @Nullable List<LocusId> locusIds, @Nullable ComponentName componentName,
            @ShortcutQuery.QueryFlags int flags, int userId, int callingPid, int callingUid);

    /**
     * Retrieves shortcuts asynchronously. Query will go through persistence layer (thus making the
     * call async) if querying by shortcutIds in a specific package; otherwise it's effectively the
     * same as calling {@link #getShortcuts}.
     */
    public abstract void
            getShortcutsAsync(int launcherUserId,
            @NonNull String callingPackage, long changedSince,
            @Nullable String packageName, @Nullable List<String> shortcutIds,
            @Nullable List<LocusId> locusIds, @Nullable ComponentName componentName,
            @ShortcutQuery.QueryFlags int flags, int userId, int callingPid, int callingUid,
            AndroidFuture<List<ShortcutInfo>> cb);

    public abstract boolean
            isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
            @NonNull String packageName, @NonNull String id, int userId);
@@ -63,6 +78,14 @@ public abstract class ShortcutServiceInternal {
            @NonNull String packageName, @NonNull String shortcutId, int userId,
            int callingPid, int callingUid);

    /**
     * Retrieves the intents from a specified shortcut asynchronously.
     */
    public abstract void createShortcutIntentsAsync(
            int launcherUserId, @NonNull String callingPackage,
            @NonNull String packageName, @NonNull String shortcutId, int userId,
            int callingPid, int callingUid, @NonNull AndroidFuture<Intent[]> cb);

    public abstract void addListener(@NonNull ShortcutChangeListener listener);

    public abstract void addShortcutChangeCallback(
@@ -82,6 +105,13 @@ public abstract class ShortcutServiceInternal {
            @NonNull String callingPackage,
            @NonNull String packageName, @NonNull String shortcutId, int userId);

    /**
     * Retrieves a file descriptor from the icon in a specified shortcut asynchronously.
     */
    public abstract void getShortcutIconFdAsync(int launcherUserId, @NonNull String callingPackage,
            @NonNull String packageName, @NonNull String shortcutId, int userId,
            @NonNull AndroidFuture<ParcelFileDescriptor> cb);

    public abstract boolean hasShortcutHostPermission(int launcherUserId,
            @NonNull String callingPackage, int callingPid, int callingUid);

@@ -117,6 +147,14 @@ public abstract class ShortcutServiceInternal {
    public abstract String getShortcutIconUri(int launcherUserId, @NonNull String launcherPackage,
            @NonNull String packageName, @NonNull String shortcutId, int userId);

    /**
     * Retrieves the icon Uri of the shortcut asynchronously, and grants Uri read permission to the
     * caller.
     */
    public abstract void getShortcutIconUriAsync(int launcherUserId,
            @NonNull String launcherPackage, @NonNull String packageName,
            @NonNull String shortcutId, int userId, @NonNull AndroidFuture<String> cb);

    public abstract boolean isSharingShortcut(int callingUserId, @NonNull String callingPackage,
            @NonNull String packageName, @NonNull String shortcutId, int userId,
            @NonNull IntentFilter filter);
+72 −10
Original line number Diff line number Diff line
@@ -88,6 +88,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
@@ -103,6 +104,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;

/**
 * Service that manages requests and callbacks for launchers that support
@@ -728,9 +730,16 @@ public class LauncherAppsService extends SystemService {
                return null;
            }

            final Intent[] intents = mShortcutServiceInternal.createShortcutIntents(
                    getCallingUserId(), callingPackage, packageName, shortcutId,
                    user.getIdentifier(), injectBinderCallingPid(), injectBinderCallingUid());
            final AndroidFuture<Intent[]> ret = new AndroidFuture<>();
            Intent[] intents;
            mShortcutServiceInternal.createShortcutIntentsAsync(getCallingUserId(),
                    callingPackage, packageName, shortcutId, user.getIdentifier(),
                    injectBinderCallingPid(), injectBinderCallingUid(), ret);
            try {
                intents = ret.get();
            } catch (InterruptedException | ExecutionException e) {
                return null;
            }
            if (intents == null || intents.length == 0) {
                return null;
            }
@@ -900,6 +909,40 @@ public class LauncherAppsService extends SystemService {
                            injectBinderCallingPid(), injectBinderCallingUid()));
        }

        @Override
        public void getShortcutsAsync(@NonNull final String callingPackage,
                @NonNull final ShortcutQueryWrapper query, @NonNull final UserHandle targetUser,
                @NonNull final AndroidFuture<List<ShortcutInfo>> cb) {
            ensureShortcutPermission(callingPackage);
            if (!canAccessProfile(targetUser.getIdentifier(), "Cannot get shortcuts")) {
                cb.complete(Collections.EMPTY_LIST);
                return;
            }

            final long changedSince = query.getChangedSince();
            final String packageName = query.getPackage();
            final List<String> shortcutIds = query.getShortcutIds();
            final List<LocusId> locusIds = query.getLocusIds();
            final ComponentName componentName = query.getActivity();
            final int flags = query.getQueryFlags();
            if (shortcutIds != null && packageName == null) {
                throw new IllegalArgumentException(
                        "To query by shortcut ID, package name must also be set");
            }
            if (locusIds != null && packageName == null) {
                throw new IllegalArgumentException(
                        "To query by locus ID, package name must also be set");
            }
            if ((query.getQueryFlags() & ShortcutQuery.FLAG_GET_PERSONS_DATA) != 0) {
                ensureStrictAccessShortcutsPermission(callingPackage);
            }

            mShortcutServiceInternal.getShortcutsAsync(getCallingUserId(),
                    callingPackage, changedSince, packageName, shortcutIds, locusIds,
                    componentName, flags, targetUser.getIdentifier(),
                    injectBinderCallingPid(), injectBinderCallingUid(), cb);
        }

        @Override
        public void registerShortcutChangeCallback(@NonNull final String callingPackage,
                @NonNull final ShortcutQueryWrapper query,
@@ -991,8 +1034,14 @@ public class LauncherAppsService extends SystemService {
                return null;
            }

            return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(),
                    callingPackage, packageName, id, targetUserId);
            final AndroidFuture<ParcelFileDescriptor> ret = new AndroidFuture<>();
            mShortcutServiceInternal.getShortcutIconFdAsync(getCallingUserId(),
                    callingPackage, packageName, id, targetUserId, ret);
            try {
                return ret.get();
            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
@@ -1003,8 +1052,14 @@ public class LauncherAppsService extends SystemService {
                return null;
            }

            return mShortcutServiceInternal.getShortcutIconUri(getCallingUserId(), callingPackage,
                    packageName, shortcutId, userId);
            final AndroidFuture<String> ret = new AndroidFuture<>();
            mShortcutServiceInternal.getShortcutIconUriAsync(getCallingUserId(), callingPackage,
                    packageName, shortcutId, userId, ret);
            try {
                return ret.get();
            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
@@ -1037,9 +1092,16 @@ public class LauncherAppsService extends SystemService {
                ensureShortcutPermission(callerUid, callerPid, callingPackage);
            }

            final Intent[] intents = mShortcutServiceInternal.createShortcutIntents(
                    callingUserId, callingPackage, packageName, shortcutId, targetUserId,
                    callerPid, callerUid);
            final AndroidFuture<Intent[]> ret = new AndroidFuture<>();
            Intent[] intents;
            mShortcutServiceInternal.createShortcutIntentsAsync(getCallingUserId(), callingPackage,
                    packageName, shortcutId, targetUserId,
                    injectBinderCallingPid(), injectBinderCallingUid(), ret);
            try {
                intents = ret.get();
            } catch (InterruptedException | ExecutionException e) {
                return false;
            }
            if (intents == null || intents.length == 0) {
                return false;
            }
Loading