Implement the AppSearch.deleteAll API.

Bug: 147636343
Test: atest CtsAppSearchTestCases FrameworksCoreTests:android.app.appsearch FrameworksServicesTests:com.android.server.appsearch.impl
Change-Id: I72dcdc950ad95e47505be00e1e190c917c8174a1
diff --git a/framework/java/android/app/appsearch/AppSearchManager.java b/framework/java/android/app/appsearch/AppSearchManager.java
index 1fb7b4b..f91773a 100644
--- a/framework/java/android/app/appsearch/AppSearchManager.java
+++ b/framework/java/android/app/appsearch/AppSearchManager.java
@@ -333,6 +333,17 @@
         return AppSearchResult.newSuccessfulResult(new SearchResults(searchResultProto));
     }
 
+    /** Deletes all documents owned by the calling app. */
+    public AppSearchResult<Void> deleteAll() {
+        AndroidFuture<AppSearchResult> future = new AndroidFuture<>();
+        try {
+            mService.deleteAll(future);
+        } catch (RemoteException e) {
+            future.completeExceptionally(e);
+        }
+        return getFutureOrThrow(future);
+    }
+
     private static <T> T getFutureOrThrow(@NonNull AndroidFuture<T> future) {
         try {
             return future.get();
diff --git a/framework/java/android/app/appsearch/IAppSearchManager.aidl b/framework/java/android/app/appsearch/IAppSearchManager.aidl
index b7100a4..b559c7d 100644
--- a/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -72,4 +72,12 @@
     void query(
         in byte[] searchSpecBytes, in byte[] resultSpecBytes, in byte[] scoringSpecBytes,
         in AndroidFuture<AppSearchResult> callback);
+
+    /**
+     * Deletes all documents belonging to the calling app.
+     *
+     * @param callback {@link AndroidFuture}&lt;{@link AppSearchResult}&lt;{@link Void}&gt;&gt;.
+     *     Will be completed with the result of the call.
+     */
+    void deleteAll(in AndroidFuture<AppSearchResult> callback);
 }
diff --git a/service/java/com/android/server/appsearch/AppSearchManagerService.java b/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 5cc5add..c61cdbc 100644
--- a/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -181,6 +181,23 @@
             }
         }
 
+        @Override
+        public void deleteAll(@NonNull AndroidFuture<AppSearchResult> callback) {
+            Preconditions.checkNotNull(callback);
+            int callingUid = Binder.getCallingUidOrThrow();
+            int callingUserId = UserHandle.getUserId(callingUid);
+            long callingIdentity = Binder.clearCallingIdentity();
+            try {
+                AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
+                impl.deleteAll(callingUid);
+                callback.complete(AppSearchResult.newSuccessfulResult(null));
+            } catch (Throwable t) {
+                callback.complete(throwableToFailedResult(t));
+            } finally {
+                Binder.restoreCallingIdentity(callingIdentity);
+            }
+        }
+
         private <ValueType> AppSearchResult<ValueType> throwableToFailedResult(
                 @NonNull Throwable t) {
             if (t instanceof AppSearchException) {
diff --git a/service/java/com/android/server/appsearch/impl/AppSearchImpl.java b/service/java/com/android/server/appsearch/impl/AppSearchImpl.java
index f0af398..9a8f945 100644
--- a/service/java/com/android/server/appsearch/impl/AppSearchImpl.java
+++ b/service/java/com/android/server/appsearch/impl/AppSearchImpl.java
@@ -209,6 +209,16 @@
     }
 
     /**
+     * Deletes all documents owned by the calling app.
+     *
+     * @param callingUid The uid of the app calling AppSearch.
+     */
+    public void deleteAll(int callingUid) {
+        String namespace = getTypePrefix(callingUid);
+        mFakeIcing.deleteByNamespace(namespace);
+    }
+
+    /**
      * Rewrites all types mentioned anywhere in {@code documentBuilder} to prepend or remove
      * {@code typePrefix}.
      *
diff --git a/service/java/com/android/server/appsearch/impl/FakeIcing.java b/service/java/com/android/server/appsearch/impl/FakeIcing.java
index fce0c80..4b7c80a 100644
--- a/service/java/com/android/server/appsearch/impl/FakeIcing.java
+++ b/service/java/com/android/server/appsearch/impl/FakeIcing.java
@@ -142,6 +142,18 @@
         }
     }
 
+    /** Deletes all documents belonging to the given namespace. */
+    public void deleteByNamespace(@NonNull String namespace) {
+        for (int i = 0; i < mDocStore.size(); i++) {
+            DocumentProto document = mDocStore.valueAt(i);
+            if (namespace.equals(document.getNamespace())) {
+                mDocStore.removeAt(i);
+                mUriToDocIdMap.remove(document.getUri());
+                i--;
+            }
+        }
+    }
+
     private void indexDocument(int docId, DocumentProto document) {
         for (PropertyProto property : document.getPropertiesList()) {
             for (String stringValue : property.getStringValuesList()) {