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