1 /* 2 * Copyright 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 // @exportToFramework:skipFile() 17 package androidx.appsearch.app; 18 19 import android.annotation.SuppressLint; 20 21 import androidx.annotation.RequiresFeature; 22 import androidx.appsearch.exceptions.AppSearchException; 23 import androidx.appsearch.flags.FlaggedApi; 24 import androidx.appsearch.flags.Flags; 25 import androidx.appsearch.observer.ObserverCallback; 26 import androidx.appsearch.observer.ObserverSpec; 27 28 import com.google.common.util.concurrent.ListenableFuture; 29 30 import org.jspecify.annotations.NonNull; 31 32 import java.io.Closeable; 33 import java.util.Set; 34 import java.util.concurrent.Executor; 35 36 /** 37 * Provides a connection to all AppSearch databases the querying application has been 38 * granted access to. 39 * 40 * <p>All implementations of this interface must be thread safe. 41 * 42 * @see AppSearchSession 43 */ 44 public interface GlobalSearchSession extends Closeable { 45 /** 46 * Retrieves {@link GenericDocument} documents, belonging to the specified package name and 47 * database name and identified by the namespace and ids in the request, from the 48 * {@link GlobalSearchSession} database. When a call is successful, the result will be 49 * returned in the successes section of the {@link AppSearchBatchResult} object in the callback. 50 * If the package doesn't exist, database doesn't exist, or if the calling package doesn't have 51 * access, these failures will be reflected as {@link AppSearchResult} objects with a 52 * RESULT_NOT_FOUND status code in the failures section of the {@link AppSearchBatchResult} 53 * object. 54 * 55 * @param packageName the name of the package to get from 56 * @param databaseName the name of the database to get from 57 * @param request a request containing a namespace and IDs of the documents to retrieve. 58 */ 59 @RequiresFeature( 60 enforcement = "androidx.appsearch.app.Features#isFeatureSupported", 61 name = Features.GLOBAL_SEARCH_SESSION_GET_BY_ID) getByDocumentIdAsync( @onNull String packageName, @NonNull String databaseName, @NonNull GetByDocumentIdRequest request)62 @NonNull ListenableFuture<AppSearchBatchResult<String, GenericDocument>> getByDocumentIdAsync( 63 @NonNull String packageName, 64 @NonNull String databaseName, 65 @NonNull GetByDocumentIdRequest request); 66 67 /** 68 * Opens a batch of AppSearch Blobs for reading. 69 * 70 * <p>See {@link AppSearchSession#openBlobForReadAsync} for a general description when a blob 71 * is open for read. 72 * 73 * <p class="caution"> 74 * The returned {@link OpenBlobForReadResponse} must be closed after use to avoid 75 * resource leaks. Failing to close it will result in system file descriptor exhaustion. 76 * </p> 77 * 78 * @param handles The {@link AppSearchBlobHandle}s that identifies the blobs. 79 * @return a response containing the readable file descriptors. 80 * 81 * @see GenericDocument.Builder#setPropertyBlobHandle 82 * 83 */ 84 @RequiresFeature( 85 enforcement = "androidx.appsearch.app.Features#isFeatureSupported", 86 name = Features.BLOB_STORAGE) 87 @FlaggedApi(Flags.FLAG_ENABLE_BLOB_STORE) 88 @ExperimentalAppSearchApi openBlobForReadAsync( @onNull Set<AppSearchBlobHandle> handles)89 default @NonNull ListenableFuture<OpenBlobForReadResponse> openBlobForReadAsync( 90 @NonNull Set<AppSearchBlobHandle> handles) { 91 throw new UnsupportedOperationException(Features.BLOB_STORAGE 92 + " is not available on this AppSearch implementation."); 93 } 94 95 /** 96 * Retrieves documents from all AppSearch databases that the querying application has access to. 97 * 98 * <p>Applications can be granted access to documents by specifying 99 * {@link SetSchemaRequest.Builder#setSchemaTypeVisibilityForPackage}, or 100 * {@link SetSchemaRequest.Builder#setDocumentClassVisibilityForPackage} when building a schema. 101 * 102 * <p>Document access can also be granted to system UIs by specifying 103 * {@link SetSchemaRequest.Builder#setSchemaTypeDisplayedBySystem}, or 104 * {@link SetSchemaRequest.Builder#setDocumentClassDisplayedBySystem} 105 * when building a schema. 106 * 107 * <p>See {@link AppSearchSession#search} for a detailed explanation on 108 * forming a query string. 109 * 110 * <p>This method is lightweight. The heavy work will be done in 111 * {@link SearchResults#getNextPageAsync}. 112 * 113 * @param queryExpression query string to search. 114 * @param searchSpec spec for setting document filters, adding projection, setting term 115 * match type, etc. 116 * @return a {@link SearchResults} object for retrieved matched documents. 117 */ search(@onNull String queryExpression, @NonNull SearchSpec searchSpec)118 @NonNull SearchResults search(@NonNull String queryExpression, @NonNull SearchSpec searchSpec); 119 120 /** 121 * Reports that a particular document has been used from a system surface. 122 * 123 * <p>See {@link AppSearchSession#reportUsageAsync} for a general description of document usage, 124 * as well as an API that can be used by the app itself. 125 * 126 * <p>Usage reported via this method is accounted separately from usage reported via 127 * {@link AppSearchSession#reportUsageAsync} and may be accessed using the constants 128 * {@link SearchSpec#RANKING_STRATEGY_SYSTEM_USAGE_COUNT} and 129 * {@link SearchSpec#RANKING_STRATEGY_SYSTEM_USAGE_LAST_USED_TIMESTAMP}. 130 * 131 * @return The pending result of performing this operation which resolves to {@code null} on 132 * success. The pending result will be completed with an 133 * {@link androidx.appsearch.exceptions.AppSearchException} with a code of 134 * {@link AppSearchResult#RESULT_SECURITY_ERROR} if this API is invoked by an app which 135 * is not part of the system. 136 */ reportSystemUsageAsync( @onNull ReportSystemUsageRequest request)137 @NonNull ListenableFuture<Void> reportSystemUsageAsync( 138 @NonNull ReportSystemUsageRequest request); 139 140 /** 141 * Retrieves the collection of schemas most recently successfully provided to 142 * {@link AppSearchSession#setSchemaAsync} for any types belonging to the requested package and 143 * database that the caller has been granted access to. 144 * 145 * <p> If the requested package/database combination does not exist or the caller has not been 146 * granted access to it, then an empty GetSchemaResponse will be returned. 147 * 148 * 149 * @param packageName the package that owns the requested {@link AppSearchSchema} instances. 150 * @param databaseName the database that owns the requested {@link AppSearchSchema} instances. 151 * @return The pending {@link GetSchemaResponse} containing the schemas that the caller has 152 * access to or an empty GetSchemaResponse if the request package and database does not 153 * exist, has not set a schema or contains no schemas that are accessible to the caller. 154 */ 155 // This call hits disk; async API prevents us from treating these calls as properties. 156 @SuppressLint("KotlinPropertyAccess") 157 @RequiresFeature( 158 enforcement = "androidx.appsearch.app.Features#isFeatureSupported", 159 name = Features.GLOBAL_SEARCH_SESSION_GET_SCHEMA) getSchemaAsync(@onNull String packageName, @NonNull String databaseName)160 @NonNull ListenableFuture<GetSchemaResponse> getSchemaAsync(@NonNull String packageName, 161 @NonNull String databaseName); 162 163 /** 164 * Returns the {@link Features} to check for the availability of certain features 165 * for this session. 166 */ getFeatures()167 @NonNull Features getFeatures(); 168 169 /** 170 * Adds an {@link ObserverCallback} to monitor changes within the databases owned by 171 * {@code targetPackageName} if they match the given 172 * {@link androidx.appsearch.observer.ObserverSpec}. 173 * 174 * <p>The observer callback is only triggered for data that changes after it is registered. No 175 * notification about existing data is sent as a result of registering an observer. To find out 176 * about existing data, you must use the {@link GlobalSearchSession#search} API. 177 * 178 * <p>If the data owned by {@code targetPackageName} is not visible to you, the registration 179 * call will succeed but no notifications will be dispatched. Notifications could start flowing 180 * later if {@code targetPackageName} changes its schema visibility settings. 181 * 182 * <p>If no package matching {@code targetPackageName} exists on the system, the registration 183 * call will succeed but no notifications will be dispatched. Notifications could start flowing 184 * later if {@code targetPackageName} is installed and starts indexing data. 185 * 186 * <p>This feature may not be available in all implementations. Check 187 * {@link Features#GLOBAL_SEARCH_SESSION_REGISTER_OBSERVER_CALLBACK} before calling this method. 188 * 189 * @param targetPackageName Package whose changes to monitor 190 * @param spec Specification of what types of changes to listen for 191 * @param executor Executor on which to call the {@code observer} callback methods. 192 * @param observer Callback to trigger when a schema or document changes 193 * @throws AppSearchException if an error occurs trying to register the observer 194 * @throws UnsupportedOperationException if this feature is not available on this 195 * AppSearch implementation. 196 */ 197 @RequiresFeature( 198 enforcement = "androidx.appsearch.app.Features#isFeatureSupported", 199 name = Features.GLOBAL_SEARCH_SESSION_REGISTER_OBSERVER_CALLBACK) registerObserverCallback( @onNull String targetPackageName, @NonNull ObserverSpec spec, @NonNull Executor executor, @NonNull ObserverCallback observer)200 void registerObserverCallback( 201 @NonNull String targetPackageName, 202 @NonNull ObserverSpec spec, 203 @NonNull Executor executor, 204 @NonNull ObserverCallback observer) throws AppSearchException; 205 206 /** 207 * Removes previously registered {@link ObserverCallback} instances from the system. 208 * 209 * <p>All instances of {@link ObserverCallback} which are registered to observe 210 * {@code targetPackageName} and compare equal to the provided callback using the provided 211 * argument's {@link ObserverCallback#equals} will be removed. 212 * 213 * <p>If no matching observers have been registered, this method has no effect. If multiple 214 * matching observers have been registered, all will be removed. 215 * 216 * <p>This feature may not be available in all implementations. Check 217 * {@link Features#GLOBAL_SEARCH_SESSION_REGISTER_OBSERVER_CALLBACK} before calling this method. 218 * 219 * @param targetPackageName Package which the observers to be removed are listening to. 220 * @param observer Callback to unregister. 221 * @throws AppSearchException if an error occurs trying to remove the observer, such 222 * as a failure to communicate with the system service 223 * in the platform backend. Note that no 224 * error will be thrown if the provided observer 225 * doesn't match any registered observer. 226 * @throws UnsupportedOperationException if this feature is not available on this 227 * AppSearch implementation. 228 */ 229 @RequiresFeature( 230 enforcement = "androidx.appsearch.app.Features#isFeatureSupported", 231 name = Features.GLOBAL_SEARCH_SESSION_REGISTER_OBSERVER_CALLBACK) unregisterObserverCallback( @onNull String targetPackageName, @NonNull ObserverCallback observer)232 void unregisterObserverCallback( 233 @NonNull String targetPackageName, @NonNull ObserverCallback observer) 234 throws AppSearchException; 235 236 /** Closes the {@link GlobalSearchSession}. */ 237 @Override close()238 void close(); 239 } 240