Loading services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java +30 −36 Original line number Diff line number Diff line Loading @@ -16,9 +16,6 @@ package com.android.server.appfunctions; import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.app.appsearch.AppSearchBatchResult; import android.app.appsearch.AppSearchManager; Loading @@ -42,10 +39,7 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; /** * A future API wrapper of {@link AppSearchSession} APIs. */ @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) /** A future API wrapper of {@link AppSearchSession} APIs. */ public class FutureAppSearchSession implements Closeable { private static final String TAG = FutureAppSearchSession.class.getSimpleName(); private final Executor mExecutor; Loading @@ -67,14 +61,14 @@ public class FutureAppSearchSession implements Closeable { /** Converts a failed app search result codes into an exception. */ @NonNull private static Exception failedResultToException(@NonNull AppSearchResult<?> appSearchResult) { public static Exception failedResultToException(@NonNull AppSearchResult<?> appSearchResult) { return switch (appSearchResult.getResultCode()) { case AppSearchResult.RESULT_INVALID_ARGUMENT -> new IllegalArgumentException( appSearchResult.getErrorMessage()); case AppSearchResult.RESULT_IO_ERROR -> new IOException( appSearchResult.getErrorMessage()); case AppSearchResult.RESULT_SECURITY_ERROR -> new SecurityException( appSearchResult.getErrorMessage()); case AppSearchResult.RESULT_INVALID_ARGUMENT -> new IllegalArgumentException(appSearchResult.getErrorMessage()); case AppSearchResult.RESULT_IO_ERROR -> new IOException(appSearchResult.getErrorMessage()); case AppSearchResult.RESULT_SECURITY_ERROR -> new SecurityException(appSearchResult.getErrorMessage()); default -> new IllegalStateException(appSearchResult.getErrorMessage()); }; } Loading Loading @@ -137,12 +131,14 @@ public class FutureAppSearchSession implements Closeable { /** Indexes documents into the AppSearchSession database. */ public AndroidFuture<AppSearchBatchResult<String, Void>> put( @NonNull PutDocumentsRequest putDocumentsRequest) { return getSessionAsync().thenCompose( return getSessionAsync() .thenCompose( session -> { AndroidFuture<AppSearchBatchResult<String, Void>> batchResultFuture = new AndroidFuture<>(); session.put(putDocumentsRequest, mExecutor, batchResultFuture::complete); session.put( putDocumentsRequest, mExecutor, batchResultFuture::complete); return batchResultFuture; }); } Loading @@ -152,10 +148,9 @@ public class FutureAppSearchSession implements Closeable { * of search provided. */ public AndroidFuture<FutureSearchResults> search( @NonNull String queryExpression, @NonNull SearchSpec searchSpec) { return getSessionAsync().thenApply( session -> session.search(queryExpression, searchSpec)) @NonNull String queryExpression, @NonNull SearchSpec searchSpec) { return getSessionAsync() .thenApply(session -> session.search(queryExpression, searchSpec)) .thenApply(result -> new FutureSearchResults(result, mExecutor)); } Loading @@ -173,8 +168,8 @@ public class FutureAppSearchSession implements Closeable { private final SearchResults mSearchResults; private final Executor mExecutor; public FutureSearchResults(@NonNull SearchResults searchResults, @NonNull Executor executor) { public FutureSearchResults( @NonNull SearchResults searchResults, @NonNull Executor executor) { mSearchResults = Objects.requireNonNull(searchResults); mExecutor = Objects.requireNonNull(executor); } Loading @@ -184,15 +179,14 @@ public class FutureAppSearchSession implements Closeable { new AndroidFuture<>(); mSearchResults.getNextPage(mExecutor, nextPageFuture::complete); return nextPageFuture.thenApply(result -> { return nextPageFuture.thenApply( result -> { if (result.isSuccess()) { return result.getResultValue(); } else { throw new RuntimeException( failedResultToException(result)); throw new RuntimeException(failedResultToException(result)); } }); } } } services/appfunctions/java/com/android/server/appfunctions/FutureGlobalSearchSession.java 0 → 100644 +94 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.appfunctions; import android.annotation.NonNull; import android.app.appsearch.AppSearchManager; import android.app.appsearch.AppSearchResult; import android.app.appsearch.GlobalSearchSession; import android.app.appsearch.exceptions.AppSearchException; import android.app.appsearch.observer.ObserverCallback; import android.app.appsearch.observer.ObserverSpec; import android.util.Slog; import com.android.internal.infra.AndroidFuture; import java.io.Closeable; import java.io.IOException; import java.util.concurrent.Executor; /** A wrapper around {@link GlobalSearchSession} that provides a future-based API. */ public class FutureGlobalSearchSession implements Closeable { private static final String TAG = FutureGlobalSearchSession.class.getSimpleName(); private final Executor mExecutor; private final AndroidFuture<AppSearchResult<GlobalSearchSession>> mSettableSessionFuture; public FutureGlobalSearchSession( @NonNull AppSearchManager appSearchManager, @NonNull Executor executor) { this.mExecutor = executor; mSettableSessionFuture = new AndroidFuture<>(); appSearchManager.createGlobalSearchSession(mExecutor, mSettableSessionFuture::complete); } private AndroidFuture<GlobalSearchSession> getSessionAsync() { return mSettableSessionFuture.thenApply( result -> { if (result.isSuccess()) { return result.getResultValue(); } else { throw new RuntimeException( FutureAppSearchSession.failedResultToException(result)); } }); } /** * Registers an observer callback for the given target package name. * * @param targetPackageName The package name of the target app. * @param spec The observer spec. * @param executor The executor to run the observer callback on. * @param observer The observer callback to register. * @return A future that completes once the observer is registered. */ public AndroidFuture<Void> registerObserverCallbackAsync( String targetPackageName, ObserverSpec spec, Executor executor, ObserverCallback observer) { return getSessionAsync() .thenCompose( session -> { try { session.registerObserverCallback( targetPackageName, spec, executor, observer); return AndroidFuture.completedFuture(null); } catch (AppSearchException e) { throw new RuntimeException(e); } }); } @Override public void close() throws IOException { try { getSessionAsync().get().close(); } catch (Exception ex) { Slog.e(TAG, "Failed to close global search session", ex); } } } services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCaller.java +0 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import android.os.UserHandle; * services are properly unbound after the operation completes or a timeout occurs. * * @param <T> Class of wrapped service. * @hide */ public interface RemoteServiceCaller<T> { Loading services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCallerImpl.java +0 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import java.util.function.Function; * Context#bindService}. * * @param <T> Class of wrapped service. * @hide */ public class RemoteServiceCallerImpl<T> implements RemoteServiceCaller<T> { private static final String TAG = "AppFunctionsServiceCall"; Loading services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ class FutureAppSearchSessionTest { fun clearData() { val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build() FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { val setSchemaRequest = SetSchemaRequest.Builder().build() val setSchemaRequest = SetSchemaRequest.Builder().setForceOverride(true).build() it.setSchema(setSchemaRequest) } } Loading Loading
services/appfunctions/java/com/android/server/appfunctions/FutureAppSearchSession.java +30 −36 Original line number Diff line number Diff line Loading @@ -16,9 +16,6 @@ package com.android.server.appfunctions; import static android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.app.appsearch.AppSearchBatchResult; import android.app.appsearch.AppSearchManager; Loading @@ -42,10 +39,7 @@ import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; /** * A future API wrapper of {@link AppSearchSession} APIs. */ @FlaggedApi(FLAG_ENABLE_APP_FUNCTION_MANAGER) /** A future API wrapper of {@link AppSearchSession} APIs. */ public class FutureAppSearchSession implements Closeable { private static final String TAG = FutureAppSearchSession.class.getSimpleName(); private final Executor mExecutor; Loading @@ -67,14 +61,14 @@ public class FutureAppSearchSession implements Closeable { /** Converts a failed app search result codes into an exception. */ @NonNull private static Exception failedResultToException(@NonNull AppSearchResult<?> appSearchResult) { public static Exception failedResultToException(@NonNull AppSearchResult<?> appSearchResult) { return switch (appSearchResult.getResultCode()) { case AppSearchResult.RESULT_INVALID_ARGUMENT -> new IllegalArgumentException( appSearchResult.getErrorMessage()); case AppSearchResult.RESULT_IO_ERROR -> new IOException( appSearchResult.getErrorMessage()); case AppSearchResult.RESULT_SECURITY_ERROR -> new SecurityException( appSearchResult.getErrorMessage()); case AppSearchResult.RESULT_INVALID_ARGUMENT -> new IllegalArgumentException(appSearchResult.getErrorMessage()); case AppSearchResult.RESULT_IO_ERROR -> new IOException(appSearchResult.getErrorMessage()); case AppSearchResult.RESULT_SECURITY_ERROR -> new SecurityException(appSearchResult.getErrorMessage()); default -> new IllegalStateException(appSearchResult.getErrorMessage()); }; } Loading Loading @@ -137,12 +131,14 @@ public class FutureAppSearchSession implements Closeable { /** Indexes documents into the AppSearchSession database. */ public AndroidFuture<AppSearchBatchResult<String, Void>> put( @NonNull PutDocumentsRequest putDocumentsRequest) { return getSessionAsync().thenCompose( return getSessionAsync() .thenCompose( session -> { AndroidFuture<AppSearchBatchResult<String, Void>> batchResultFuture = new AndroidFuture<>(); session.put(putDocumentsRequest, mExecutor, batchResultFuture::complete); session.put( putDocumentsRequest, mExecutor, batchResultFuture::complete); return batchResultFuture; }); } Loading @@ -152,10 +148,9 @@ public class FutureAppSearchSession implements Closeable { * of search provided. */ public AndroidFuture<FutureSearchResults> search( @NonNull String queryExpression, @NonNull SearchSpec searchSpec) { return getSessionAsync().thenApply( session -> session.search(queryExpression, searchSpec)) @NonNull String queryExpression, @NonNull SearchSpec searchSpec) { return getSessionAsync() .thenApply(session -> session.search(queryExpression, searchSpec)) .thenApply(result -> new FutureSearchResults(result, mExecutor)); } Loading @@ -173,8 +168,8 @@ public class FutureAppSearchSession implements Closeable { private final SearchResults mSearchResults; private final Executor mExecutor; public FutureSearchResults(@NonNull SearchResults searchResults, @NonNull Executor executor) { public FutureSearchResults( @NonNull SearchResults searchResults, @NonNull Executor executor) { mSearchResults = Objects.requireNonNull(searchResults); mExecutor = Objects.requireNonNull(executor); } Loading @@ -184,15 +179,14 @@ public class FutureAppSearchSession implements Closeable { new AndroidFuture<>(); mSearchResults.getNextPage(mExecutor, nextPageFuture::complete); return nextPageFuture.thenApply(result -> { return nextPageFuture.thenApply( result -> { if (result.isSuccess()) { return result.getResultValue(); } else { throw new RuntimeException( failedResultToException(result)); throw new RuntimeException(failedResultToException(result)); } }); } } }
services/appfunctions/java/com/android/server/appfunctions/FutureGlobalSearchSession.java 0 → 100644 +94 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.appfunctions; import android.annotation.NonNull; import android.app.appsearch.AppSearchManager; import android.app.appsearch.AppSearchResult; import android.app.appsearch.GlobalSearchSession; import android.app.appsearch.exceptions.AppSearchException; import android.app.appsearch.observer.ObserverCallback; import android.app.appsearch.observer.ObserverSpec; import android.util.Slog; import com.android.internal.infra.AndroidFuture; import java.io.Closeable; import java.io.IOException; import java.util.concurrent.Executor; /** A wrapper around {@link GlobalSearchSession} that provides a future-based API. */ public class FutureGlobalSearchSession implements Closeable { private static final String TAG = FutureGlobalSearchSession.class.getSimpleName(); private final Executor mExecutor; private final AndroidFuture<AppSearchResult<GlobalSearchSession>> mSettableSessionFuture; public FutureGlobalSearchSession( @NonNull AppSearchManager appSearchManager, @NonNull Executor executor) { this.mExecutor = executor; mSettableSessionFuture = new AndroidFuture<>(); appSearchManager.createGlobalSearchSession(mExecutor, mSettableSessionFuture::complete); } private AndroidFuture<GlobalSearchSession> getSessionAsync() { return mSettableSessionFuture.thenApply( result -> { if (result.isSuccess()) { return result.getResultValue(); } else { throw new RuntimeException( FutureAppSearchSession.failedResultToException(result)); } }); } /** * Registers an observer callback for the given target package name. * * @param targetPackageName The package name of the target app. * @param spec The observer spec. * @param executor The executor to run the observer callback on. * @param observer The observer callback to register. * @return A future that completes once the observer is registered. */ public AndroidFuture<Void> registerObserverCallbackAsync( String targetPackageName, ObserverSpec spec, Executor executor, ObserverCallback observer) { return getSessionAsync() .thenCompose( session -> { try { session.registerObserverCallback( targetPackageName, spec, executor, observer); return AndroidFuture.completedFuture(null); } catch (AppSearchException e) { throw new RuntimeException(e); } }); } @Override public void close() throws IOException { try { getSessionAsync().get().close(); } catch (Exception ex) { Slog.e(TAG, "Failed to close global search session", ex); } } }
services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCaller.java +0 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import android.os.UserHandle; * services are properly unbound after the operation completes or a timeout occurs. * * @param <T> Class of wrapped service. * @hide */ public interface RemoteServiceCaller<T> { Loading
services/appfunctions/java/com/android/server/appfunctions/RemoteServiceCallerImpl.java +0 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ import java.util.function.Function; * Context#bindService}. * * @param <T> Class of wrapped service. * @hide */ public class RemoteServiceCallerImpl<T> implements RemoteServiceCaller<T> { private static final String TAG = "AppFunctionsServiceCall"; Loading
services/tests/appfunctions/src/com/android/server/appfunctions/FutureAppSearchSessionTest.kt +1 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ class FutureAppSearchSessionTest { fun clearData() { val searchContext = AppSearchManager.SearchContext.Builder(TEST_DB).build() FutureAppSearchSession(appSearchManager, testExecutor, searchContext).use { val setSchemaRequest = SetSchemaRequest.Builder().build() val setSchemaRequest = SetSchemaRequest.Builder().setForceOverride(true).build() it.setSchema(setSchemaRequest) } } Loading