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}<{@link AppSearchResult}<{@link Void}>>.
+ * 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()) {