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

Commit ed02dd83 authored by Alexander Dorokhine's avatar Alexander Dorokhine
Browse files

Implement the AppSearch.delete API.

Bug: 147636343
Test: atest CtsAppSearchTestCases FrameworksCoreTests:android.app.appsearch FrameworksServicesTests:com.android.server.appsearch.impl
Change-Id: I5fc2697c873591506c172561228e0291dc17ab2d
parent cf21bb68
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -333,6 +333,27 @@ public class AppSearchManager {
        return AppSearchResult.newSuccessfulResult(new SearchResults(searchResultProto));
    }

    /**
     * Deletes {@link AppSearchDocument}s by URI.
     *
     * <p>You should not call this method directly; instead, use the {@code AppSearch#delete()} API
     * provided by JetPack.
     *
     * @param uris URIs of the documents to delete
     * @return An {@link AppSearchBatchResult} mapping each URI to a {@code null} success if
     *     deletion was successful, to a {@code null} failure if the document did not exist, or to a
     *     {@code throwable} failure if deletion failed for another reason.
     */
    public AppSearchBatchResult<String, Void> delete(@NonNull List<String> uris) {
        AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
        try {
            mService.delete(uris, future);
        } catch (RemoteException e) {
            future.completeExceptionally(e);
        }
        return getFutureOrThrow(future);
    }

    /** Deletes all documents owned by the calling app. */
    public AppSearchResult<Void> deleteAll() {
        AndroidFuture<AppSearchResult> future = new AndroidFuture<>();
+14 −0
Original line number Diff line number Diff line
@@ -73,6 +73,20 @@ interface IAppSearchManager {
        in byte[] searchSpecBytes, in byte[] resultSpecBytes, in byte[] scoringSpecBytes,
        in AndroidFuture<AppSearchResult> callback);

    /**
     * Deletes documents by URI.
     *
     * @param uris The URIs of the documents to delete
     * @param callback
     *     {@link AndroidFuture}&lt;{@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;&gt;.
     *     If the call fails to start, {@code callback} will be completed exceptionally. Otherwise,
     *     {@code callback} will be completed with an
     *     {@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;
     *     where the keys are document URIs. If a document doesn't exist, it will be reported as a
     *     failure where the {@code throwable} is {@code null}.
     */
    void delete(in List<String> uris, in AndroidFuture<AppSearchBatchResult> callback);

    /**
     * Deletes all documents belonging to the calling app.
     *
+32 −0
Original line number Diff line number Diff line
@@ -181,6 +181,38 @@ public class AppSearchManagerService extends SystemService {
            }
        }

        @Override
        public void delete(List<String> uris, AndroidFuture<AppSearchBatchResult> callback) {
            Preconditions.checkNotNull(uris);
            Preconditions.checkNotNull(callback);
            int callingUid = Binder.getCallingUidOrThrow();
            int callingUserId = UserHandle.getUserId(callingUid);
            long callingIdentity = Binder.clearCallingIdentity();
            try {
                AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
                AppSearchBatchResult.Builder<String, Void> resultBuilder =
                        new AppSearchBatchResult.Builder<>();
                for (int i = 0; i < uris.size(); i++) {
                    String uri = uris.get(i);
                    try {
                        if (!impl.delete(callingUid, uri)) {
                            resultBuilder.setFailure(
                                    uri, AppSearchResult.RESULT_NOT_FOUND, /*errorMessage=*/ null);
                        } else {
                            resultBuilder.setSuccess(uri, /*value= */null);
                        }
                    } catch (Throwable t) {
                        resultBuilder.setResult(uri, throwableToFailedResult(t));
                    }
                }
                callback.complete(resultBuilder.build());
            } catch (Throwable t) {
                callback.completeExceptionally(t);
            } finally {
                Binder.restoreCallingIdentity(callingIdentity);
            }
        }

        @Override
        public void deleteAll(@NonNull AndroidFuture<AppSearchResult> callback) {
            Preconditions.checkNotNull(callback);
+22 −0
Original line number Diff line number Diff line
@@ -129,6 +129,9 @@ public final class AppSearchImpl {
    public DocumentProto getDocument(int callingUid, @NonNull String uri) {
        String typePrefix = getTypePrefix(callingUid);
        DocumentProto document = mFakeIcing.get(uri);
        if (document == null) {
            return null;
        }

        // TODO(b/146526096): Since FakeIcing doesn't currently handle namespaces, we perform a
        //  post-filter to make sure we don't return documents we shouldn't. This should be removed
@@ -208,6 +211,25 @@ public final class AppSearchImpl {
        return searchResultsBuilder.build();
    }

    /** Deletes the given document by URI */
    public boolean delete(int callingUid, @NonNull String uri) {
        DocumentProto document = mFakeIcing.get(uri);
        if (document == null) {
            return false;
        }

        // TODO(b/146526096): Since FakeIcing doesn't currently handle namespaces, we perform a
        //     post-filter to make sure we don't delete documents we shouldn't. This should be
        //     removed once the real Icing Lib is implemented.
        String typePrefix = getTypePrefix(callingUid);
        if (!typePrefix.equals(document.getNamespace())) {
            throw new SecurityException(
                    "Failed to delete document " + uri + "; URI collision in FakeIcing");
        }

        return mFakeIcing.delete(uri);
    }

    /**
     * Deletes all documents owned by the calling app.
     *
+5 −2
Original line number Diff line number Diff line
@@ -131,18 +131,21 @@ public class FakeIcing {
     * Deletes a document by its URI.
     *
     * @param uri The URI of the document to be deleted.
     * @return Whether deletion was successful.
     */
    public void delete(@NonNull String uri) {
    public boolean delete(@NonNull String uri) {
        // Update mDocIdMap
        Integer docId = mUriToDocIdMap.get(uri);
        if (docId != null) {
            // Delete the old doc
            mDocStore.remove(docId);
            mUriToDocIdMap.remove(uri);
            return true;
        }
        return false;
    }

    /** Deletes all documents belonging to the given namespace. */
    /** Deletes all documents having the given namespace. */
    public void deleteByNamespace(@NonNull String namespace) {
        for (int i = 0; i < mDocStore.size(); i++) {
            DocumentProto document = mDocStore.valueAt(i);