Merge "Update framework from jetpack." into sc-dev

This commit is contained in:
Alexander Dorokhine
2021-04-21 23:17:21 +00:00
committed by Android (Google) Code Review
42 changed files with 1345 additions and 1017 deletions

View File

@@ -79,15 +79,14 @@ package android.app.appsearch {
public static final class AppSearchSchema.DocumentPropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig {
method @NonNull public String getSchemaType();
method public boolean isIndexNestedProperties();
method public boolean shouldIndexNestedProperties();
}
public static final class AppSearchSchema.DocumentPropertyConfig.Builder {
ctor public AppSearchSchema.DocumentPropertyConfig.Builder(@NonNull String);
ctor public AppSearchSchema.DocumentPropertyConfig.Builder(@NonNull String, @NonNull String);
method @NonNull public android.app.appsearch.AppSearchSchema.DocumentPropertyConfig build();
method @NonNull public android.app.appsearch.AppSearchSchema.DocumentPropertyConfig.Builder setCardinality(int);
method @NonNull public android.app.appsearch.AppSearchSchema.DocumentPropertyConfig.Builder setIndexNestedProperties(boolean);
method @NonNull public android.app.appsearch.AppSearchSchema.DocumentPropertyConfig.Builder setSchemaType(@NonNull String);
method @NonNull public android.app.appsearch.AppSearchSchema.DocumentPropertyConfig.Builder setShouldIndexNestedProperties(boolean);
}
public static final class AppSearchSchema.DoublePropertyConfig extends android.app.appsearch.AppSearchSchema.PropertyConfig {
@@ -136,12 +135,12 @@ package android.app.appsearch {
public final class AppSearchSession implements java.io.Closeable {
method public void close();
method public void getByUri(@NonNull android.app.appsearch.GetByUriRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,android.app.appsearch.GenericDocument>);
method public void getByDocumentId(@NonNull android.app.appsearch.GetByDocumentIdRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,android.app.appsearch.GenericDocument>);
method public void getNamespaces(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.util.Set<java.lang.String>>>);
method public void getSchema(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<android.app.appsearch.GetSchemaResponse>>);
method public void getStorageInfo(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<android.app.appsearch.StorageInfo>>);
method public void put(@NonNull android.app.appsearch.PutDocumentsRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,java.lang.Void>);
method public void remove(@NonNull android.app.appsearch.RemoveByUriRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,java.lang.Void>);
method public void remove(@NonNull android.app.appsearch.RemoveByDocumentIdRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,java.lang.Void>);
method public void remove(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.lang.Void>>);
method public void reportUsage(@NonNull android.app.appsearch.ReportUsageRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.lang.Void>>);
method @NonNull public android.app.appsearch.SearchResults search(@NonNull String, @NonNull android.app.appsearch.SearchSpec);
@@ -156,6 +155,7 @@ package android.app.appsearch {
public class GenericDocument {
ctor protected GenericDocument(@NonNull android.app.appsearch.GenericDocument);
method public long getCreationTimestampMillis();
method @NonNull public String getId();
method public static int getMaxIndexedProperties();
method @NonNull public String getNamespace();
method @Nullable public Object getProperty(@NonNull String);
@@ -175,7 +175,6 @@ package android.app.appsearch {
method @NonNull public String getSchemaType();
method public int getScore();
method public long getTtlMillis();
method @NonNull public String getUri();
}
public static class GenericDocument.Builder<BuilderType extends android.app.appsearch.GenericDocument.Builder> {
@@ -192,19 +191,19 @@ package android.app.appsearch {
method @NonNull public BuilderType setTtlMillis(long);
}
public final class GetByUriRequest {
public final class GetByDocumentIdRequest {
method @NonNull public java.util.Set<java.lang.String> getIds();
method @NonNull public String getNamespace();
method @NonNull public java.util.Map<java.lang.String,java.util.List<java.lang.String>> getProjections();
method @NonNull public java.util.Set<java.lang.String> getUris();
field public static final String PROJECTION_SCHEMA_TYPE_WILDCARD = "*";
}
public static final class GetByUriRequest.Builder {
ctor public GetByUriRequest.Builder(@NonNull String);
method @NonNull public android.app.appsearch.GetByUriRequest.Builder addProjection(@NonNull String, @NonNull java.util.Collection<java.lang.String>);
method @NonNull public android.app.appsearch.GetByUriRequest.Builder addUris(@NonNull java.lang.String...);
method @NonNull public android.app.appsearch.GetByUriRequest.Builder addUris(@NonNull java.util.Collection<java.lang.String>);
method @NonNull public android.app.appsearch.GetByUriRequest build();
public static final class GetByDocumentIdRequest.Builder {
ctor public GetByDocumentIdRequest.Builder(@NonNull String);
method @NonNull public android.app.appsearch.GetByDocumentIdRequest.Builder addIds(@NonNull java.lang.String...);
method @NonNull public android.app.appsearch.GetByDocumentIdRequest.Builder addIds(@NonNull java.util.Collection<java.lang.String>);
method @NonNull public android.app.appsearch.GetByDocumentIdRequest.Builder addProjection(@NonNull String, @NonNull java.util.Collection<java.lang.String>);
method @NonNull public android.app.appsearch.GetByDocumentIdRequest build();
}
public class GetSchemaResponse {
@@ -249,44 +248,42 @@ package android.app.appsearch {
method @NonNull public android.app.appsearch.PutDocumentsRequest build();
}
public final class RemoveByUriRequest {
public final class RemoveByDocumentIdRequest {
method @NonNull public java.util.Set<java.lang.String> getIds();
method @NonNull public String getNamespace();
method @NonNull public java.util.Set<java.lang.String> getUris();
}
public static final class RemoveByUriRequest.Builder {
ctor public RemoveByUriRequest.Builder(@NonNull String);
method @NonNull public android.app.appsearch.RemoveByUriRequest.Builder addUris(@NonNull java.lang.String...);
method @NonNull public android.app.appsearch.RemoveByUriRequest.Builder addUris(@NonNull java.util.Collection<java.lang.String>);
method @NonNull public android.app.appsearch.RemoveByUriRequest build();
public static final class RemoveByDocumentIdRequest.Builder {
ctor public RemoveByDocumentIdRequest.Builder(@NonNull String);
method @NonNull public android.app.appsearch.RemoveByDocumentIdRequest.Builder addIds(@NonNull java.lang.String...);
method @NonNull public android.app.appsearch.RemoveByDocumentIdRequest.Builder addIds(@NonNull java.util.Collection<java.lang.String>);
method @NonNull public android.app.appsearch.RemoveByDocumentIdRequest build();
}
public final class ReportSystemUsageRequest {
method @NonNull public String getDatabaseName();
method @NonNull public String getDocumentId();
method @NonNull public String getNamespace();
method @NonNull public String getPackageName();
method @NonNull public String getUri();
method public long getUsageTimeMillis();
method public long getUsageTimestampMillis();
}
public static final class ReportSystemUsageRequest.Builder {
ctor public ReportSystemUsageRequest.Builder(@NonNull String, @NonNull String, @NonNull String);
ctor public ReportSystemUsageRequest.Builder(@NonNull String, @NonNull String, @NonNull String, @NonNull String);
method @NonNull public android.app.appsearch.ReportSystemUsageRequest build();
method @NonNull public android.app.appsearch.ReportSystemUsageRequest.Builder setUri(@NonNull String);
method @NonNull public android.app.appsearch.ReportSystemUsageRequest.Builder setUsageTimeMillis(long);
method @NonNull public android.app.appsearch.ReportSystemUsageRequest.Builder setUsageTimestampMillis(long);
}
public final class ReportUsageRequest {
method @NonNull public String getDocumentId();
method @NonNull public String getNamespace();
method @NonNull public String getUri();
method public long getUsageTimeMillis();
method public long getUsageTimestampMillis();
}
public static final class ReportUsageRequest.Builder {
ctor public ReportUsageRequest.Builder(@NonNull String);
ctor public ReportUsageRequest.Builder(@NonNull String, @NonNull String);
method @NonNull public android.app.appsearch.ReportUsageRequest build();
method @NonNull public android.app.appsearch.ReportUsageRequest.Builder setUri(@NonNull String);
method @NonNull public android.app.appsearch.ReportUsageRequest.Builder setUsageTimeMillis(long);
method @NonNull public android.app.appsearch.ReportUsageRequest.Builder setUsageTimestampMillis(long);
}
public final class SearchResult {
@@ -315,10 +312,9 @@ package android.app.appsearch {
}
public static final class SearchResult.MatchInfo.Builder {
ctor public SearchResult.MatchInfo.Builder();
ctor public SearchResult.MatchInfo.Builder(@NonNull String);
method @NonNull public android.app.appsearch.SearchResult.MatchInfo build();
method @NonNull public android.app.appsearch.SearchResult.MatchInfo.Builder setExactMatchRange(@NonNull android.app.appsearch.SearchResult.MatchRange);
method @NonNull public android.app.appsearch.SearchResult.MatchInfo.Builder setPropertyPath(@NonNull String);
method @NonNull public android.app.appsearch.SearchResult.MatchInfo.Builder setSnippetRange(@NonNull android.app.appsearch.SearchResult.MatchRange);
}
@@ -427,19 +423,11 @@ package android.app.appsearch {
}
public static class SetSchemaResponse.MigrationFailure {
ctor public SetSchemaResponse.MigrationFailure(@NonNull String, @NonNull String, @NonNull String, @NonNull android.app.appsearch.AppSearchResult<?>);
method @NonNull public android.app.appsearch.AppSearchResult<java.lang.Void> getAppSearchResult();
method @NonNull public String getDocumentId();
method @NonNull public String getNamespace();
method @NonNull public String getSchemaType();
method @NonNull public String getUri();
}
public static final class SetSchemaResponse.MigrationFailure.Builder {
ctor public SetSchemaResponse.MigrationFailure.Builder();
method @NonNull public android.app.appsearch.SetSchemaResponse.MigrationFailure build();
method @NonNull public android.app.appsearch.SetSchemaResponse.MigrationFailure.Builder setAppSearchResult(@NonNull android.app.appsearch.AppSearchResult<java.lang.Void>);
method @NonNull public android.app.appsearch.SetSchemaResponse.MigrationFailure.Builder setNamespace(@NonNull String);
method @NonNull public android.app.appsearch.SetSchemaResponse.MigrationFailure.Builder setSchemaType(@NonNull String);
method @NonNull public android.app.appsearch.SetSchemaResponse.MigrationFailure.Builder setUri(@NonNull String);
}
public class StorageInfo {

View File

@@ -40,7 +40,7 @@ import java.util.Objects;
* both successes and failures.
*
* @see AppSearchSession#put
* @see AppSearchSession#getByUri
* @see AppSearchSession#getByDocumentId
* @see AppSearchSession#remove
*/
public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelable {
@@ -87,8 +87,9 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl
* Returns a {@link Map} of keys mapped to instances of the value type for all successful
* individual results.
*
* <p>Example: {@link AppSearchSession#getByUri} returns an {@link AppSearchBatchResult}. Each
* key (a URI of {@code String} type) will map to a {@link GenericDocument} object.
* <p>Example: {@link AppSearchSession#getByDocumentId} returns an {@link AppSearchBatchResult}.
* Each key (the document ID, of {@code String} type) will map to a {@link GenericDocument}
* object.
*
* <p>The values of the {@link Map} will not be {@code null}.
*/

View File

@@ -78,10 +78,10 @@ import java.util.function.Consumer;
* });</pre>
*
* <p>The basic unit of data in AppSearch is represented as a {@link GenericDocument} object,
* containing a URI, namespace, time-to-live, score, and properties. A namespace organizes a logical
* containing an ID, namespace, time-to-live, score, and properties. A namespace organizes a logical
* group of documents. For example, a namespace can be created to group documents on a per-account
* basis. A URI identifies a single document within a namespace. The combination of URI and
* namespace uniquely identifies a {@link GenericDocument} in the database.
* basis. An ID identifies a single document within a namespace. The combination of namespace and ID
* uniquely identifies a {@link GenericDocument} in the database.
*
* <p>Once the schema has been set, {@link GenericDocument} objects can be put into the database and
* indexed by calling {@link AppSearchSession#put}.
@@ -91,8 +91,7 @@ import java.util.function.Consumer;
* <pre>
* // Although for this example we use GenericDocument directly, we recommend extending
* // GenericDocument to create specific types (i.e. Email) with specific setters/getters.
* GenericDocument email = new GenericDocument.Builder<>(URI, EMAIL_SCHEMA_TYPE)
* .setNamespace(NAMESPACE)
* GenericDocument email = new GenericDocument.Builder<>(NAMESPACE, ID, EMAIL_SCHEMA_TYPE)
* .setPropertyString(“subject”, EMAIL_SUBJECT)
* .setScore(EMAIL_SCORE)
* .build();
@@ -108,13 +107,13 @@ import java.util.function.Consumer;
* <p>Searching within the database is done by calling {@link AppSearchSession#search} and providing
* the query string to search for, as well as a {@link SearchSpec}.
*
* <p>Alternatively, {@link AppSearchSession#getByUri} can be called to retrieve documents by URI
* and namespace.
* <p>Alternatively, {@link AppSearchSession#getByDocumentId} can be called to retrieve documents by
* namespace and ID.
*
* <p>Document removal is done either by time-to-live expiration, or explicitly calling a remove
* operation. Remove operations can be done by URI and namespace via {@link
* AppSearchSession#remove(RemoveByUriRequest, Executor, BatchResultCallback)}, or by query via
* {@link AppSearchSession#remove(String, SearchSpec, Executor, Consumer)}.
* operation. Remove operations can be done by namespace and ID via {@link
* AppSearchSession#remove(RemoveByDocumentIdRequest, Executor, BatchResultCallback)}, or by query
* via {@link AppSearchSession#remove(String, SearchSpec, Executor, Consumer)}.
*/
@SystemService(Context.APP_SEARCH_SERVICE)
public class AppSearchManager {

View File

@@ -41,10 +41,14 @@ import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
* Represents a connection to an AppSearch storage system where {@link GenericDocument}s can be
* placed and queried.
* Provides a connection to a single AppSearch database.
*
* <p>An {@link AppSearchSession} instance provides access to database operations such as
* setting a schema, adding documents, and searching.
*
* <p>This class is thread safe.
*
* @see GlobalSearchSession
*/
public final class AppSearchSession implements Closeable {
private static final String TAG = "AppSearchSession";
@@ -250,12 +254,12 @@ public final class AppSearchSession implements Closeable {
* @param request containing documents to be indexed.
* @param executor Executor on which to invoke the callback.
* @param callback Callback to receive pending result of performing this operation. The keys
* of the returned {@link AppSearchBatchResult} are the URIs of the input
* of the returned {@link AppSearchBatchResult} are the IDs of the input
* documents. The values are {@code null} if they were successfully indexed,
* or a failed {@link AppSearchResult} otherwise.
* Or {@link BatchResultCallback#onSystemError} will be invoked with a
* {@link Throwable} if an unexpected internal error occurred in AppSearch
* service.
* or a failed {@link AppSearchResult} otherwise. If an unexpected internal
* error occurs in the AppSearch service,
* {@link BatchResultCallback#onSystemError} will be invoked with a
* {@link Throwable}.
*/
public void put(
@NonNull PutDocumentsRequest request,
@@ -291,23 +295,22 @@ public final class AppSearchSession implements Closeable {
}
/**
* Gets {@link GenericDocument} objects by URIs and namespace from the {@link AppSearchSession}
* database.
* Gets {@link GenericDocument} objects by document IDs in a namespace from the {@link
* AppSearchSession} database.
*
* @param request a request containing URIs and namespace to get documents for.
* @param request a request containing a namespace and IDs to get documents for.
* @param executor Executor on which to invoke the callback.
* @param callback Callback to receive the pending result of performing this operation. The keys
* of the returned {@link AppSearchBatchResult} are the input URIs. The values
* of the returned {@link AppSearchBatchResult} are the input IDs. The values
* are the returned {@link GenericDocument}s on success, or a failed
* {@link AppSearchResult} otherwise. URIs that are not found will return a
* {@link AppSearchResult} otherwise. IDs that are not found will return a
* failed {@link AppSearchResult} with a result code of
* {@link AppSearchResult#RESULT_NOT_FOUND}.
* Or {@link BatchResultCallback#onSystemError} will be invoked with a
* {@link Throwable} if an unexpected internal error occurred in AppSearch
* service.
* {@link AppSearchResult#RESULT_NOT_FOUND}. If an unexpected internal error
* occurs in the AppSearch service, {@link BatchResultCallback#onSystemError}
* will be invoked with a {@link Throwable}.
*/
public void getByUri(
@NonNull GetByUriRequest request,
public void getByDocumentId(
@NonNull GetByDocumentIdRequest request,
@NonNull @CallbackExecutor Executor executor,
@NonNull BatchResultCallback<String, GenericDocument> callback) {
Objects.requireNonNull(request);
@@ -319,7 +322,7 @@ public final class AppSearchSession implements Closeable {
mPackageName,
mDatabaseName,
request.getNamespace(),
new ArrayList<>(request.getUris()),
new ArrayList<>(request.getIds()),
request.getProjectionsInternal(),
mUserId,
new IAppSearchBatchResultCallback.Stub() {
@@ -373,8 +376,8 @@ public final class AppSearchSession implements Closeable {
}
/**
* Retrieves documents from the open {@link AppSearchSession} that match a given query string
* and type of search provided.
* Retrieves documents from the open {@link AppSearchSession} that match a given query
* string and type of search provided.
*
* <p>Query strings can be empty, contain one term with no operators, or contain multiple terms
* and operators.
@@ -441,7 +444,7 @@ public final class AppSearchSession implements Closeable {
}
/**
* Reports usage of a particular document by URI and namespace.
* Reports usage of a particular document by namespace and ID.
*
* <p>A usage report represents an event in which a user interacted with or viewed a document.
*
@@ -470,8 +473,8 @@ public final class AppSearchSession implements Closeable {
mPackageName,
mDatabaseName,
request.getNamespace(),
request.getUri(),
request.getUsageTimeMillis(),
request.getDocumentId(),
request.getUsageTimestampMillis(),
/*systemUsage=*/ false,
mUserId,
new IAppSearchResultCallback.Stub() {
@@ -486,29 +489,29 @@ public final class AppSearchSession implements Closeable {
}
/**
* Removes {@link GenericDocument} objects by URIs and namespace from the {@link
* Removes {@link GenericDocument} objects by document IDs in a namespace from the {@link
* AppSearchSession} database.
*
* <p>Removed documents will no longer be surfaced by {@link #search} or {@link #getByUri}
* calls.
* <p>Removed documents will no longer be surfaced by {@link #search} or {@link
* #getByDocumentId} calls.
*
* <p><b>NOTE:</b>By default, documents are removed via a soft delete operation. Once the
* document crosses the count threshold or byte usage threshold, the documents will be removed
* from disk.
* <p>Once the database crosses the document count or byte usage threshold, removed documents
* will be deleted from disk.
*
* @param request {@link RemoveByUriRequest} with URIs and namespace to remove from the index.
* @param request {@link RemoveByDocumentIdRequest} with IDs in a namespace to remove from the
* index.
* @param executor Executor on which to invoke the callback.
* @param callback Callback to receive the pending result of performing this operation. The keys
* of the returned {@link AppSearchBatchResult} are the input URIs. The values
* are {@code null} on success, or a failed {@link AppSearchResult} otherwise.
* URIs that are not found will return a failed {@link AppSearchResult} with a
* result code of {@link AppSearchResult#RESULT_NOT_FOUND}.
* Or {@link BatchResultCallback#onSystemError} will be invoked with a
* {@link Throwable} if an unexpected internal error occurred in AppSearch
* service.
* of the returned {@link AppSearchBatchResult} are the input document IDs. The
* values are {@code null} on success, or a failed {@link AppSearchResult}
* otherwise. IDs that are not found will return a failed
* {@link AppSearchResult} with a result code of
* {@link AppSearchResult#RESULT_NOT_FOUND}. If an unexpected internal error
* occurs in the AppSearch service, {@link BatchResultCallback#onSystemError}
* will be invoked with a {@link Throwable}.
*/
public void remove(
@NonNull RemoveByUriRequest request,
@NonNull RemoveByDocumentIdRequest request,
@NonNull @CallbackExecutor Executor executor,
@NonNull BatchResultCallback<String, Void> callback) {
Objects.requireNonNull(request);
@@ -516,8 +519,8 @@ public final class AppSearchSession implements Closeable {
Objects.requireNonNull(callback);
Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
try {
mService.removeByUri(mPackageName, mDatabaseName, request.getNamespace(),
new ArrayList<>(request.getUris()), mUserId,
mService.removeByDocumentId(mPackageName, mDatabaseName, request.getNamespace(),
new ArrayList<>(request.getIds()), mUserId,
new IAppSearchBatchResultCallback.Stub() {
@Override
public void onResult(AppSearchBatchResult result) {
@@ -581,8 +584,8 @@ public final class AppSearchSession implements Closeable {
/**
* Gets the storage info for this {@link AppSearchSession} database.
*
* <p>This may take time proportional to the number of documents and may be inefficient to
* call repeatedly.
* <p>This may take time proportional to the number of documents and may be inefficient to call
* repeatedly.
*
* @param executor Executor on which to invoke the callback.
* @param callback Callback to receive the storage info.
@@ -618,8 +621,8 @@ public final class AppSearchSession implements Closeable {
}
/**
* Closes the {@link AppSearchSession} to persist all schema and document updates, additions,
* and deletes to disk.
* Closes the {@link AppSearchSession} to persist all schema and document updates,
* additions, and deletes to disk.
*/
@Override
public void close() {

View File

@@ -31,9 +31,12 @@ import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
* This class provides global access to the centralized AppSearch index maintained by the system.
* Provides a connection to all AppSearch databases the querying application has been granted access
* to.
*
* <p>Apps can retrieve indexed documents through the {@link #search} API.
* <p>This class is thread safe.
*
* @see AppSearchSession
*/
public class GlobalSearchSession implements Closeable {
private static final String TAG = "AppSearchGlobalSearchSe";
@@ -151,8 +154,8 @@ public class GlobalSearchSession implements Closeable {
request.getPackageName(),
request.getDatabaseName(),
request.getNamespace(),
request.getUri(),
request.getUsageTimeMillis(),
request.getDocumentId(),
request.getUsageTimestampMillis(),
/*systemUsage=*/ true,
mUserId,
new IAppSearchResultCallback.Stub() {

View File

@@ -100,7 +100,7 @@ interface IAppSearchManager {
* will be called with the cause throwable. Otherwise,
* {@link IAppSearchBatchResultCallback#onResult} will be called with an
* {@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;
* where the keys are document URIs, and the values are {@code null}.
* where the keys are document IDs, and the values are {@code null}.
*/
void putDocuments(
in String packageName,
@@ -116,7 +116,7 @@ interface IAppSearchManager {
* @param packageName The name of the package that owns this document.
* @param databaseName The databaseName this document resides in.
* @param namespace The namespace this document resides in.
* @param uris The URIs of the documents to retrieve
* @param ids The IDs of the documents to retrieve
* @param typePropertyPaths A map of schema type to a list of property paths to return in the
* result.
* @param userId Id of the calling user
@@ -125,13 +125,13 @@ interface IAppSearchManager {
* will be called with the cause throwable. Otherwise,
* {@link IAppSearchBatchResultCallback#onResult} will be called with an
* {@link AppSearchBatchResult}&lt;{@link String}, {@link Bundle}&gt;
* where the keys are document URIs, and the values are Document bundles.
* where the keys are document IDs, and the values are Document bundles.
*/
void getDocuments(
in String packageName,
in String databaseName,
in String namespace,
in List<String> uris,
in List<String> ids,
in Map<String, List<String>> typePropertyPaths,
in int userId,
in IAppSearchBatchResultCallback callback);
@@ -235,7 +235,7 @@ interface IAppSearchManager {
in IAppSearchResultCallback callback);
/**
* Reports usage of a particular document by URI and namespace.
* Reports usage of a particular document by namespace and id.
*
* <p>A usage report represents an event in which a user interacted with or viewed a document.
*
@@ -249,8 +249,8 @@ interface IAppSearchManager {
* @param packageName The name of the package that owns this document.
* @param databaseName The name of the database to report usage against.
* @param namespace Namespace the document being used belongs to.
* @param uri URI of the document being used.
* @param usageTimeMillis The timestamp at which the document was used.
* @param id ID of the document being used.
* @param usageTimestampMillis The timestamp at which the document was used.
* @param systemUsage Whether the usage was reported by a system app against another app's doc.
* @param userId Id of the calling user
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
@@ -260,33 +260,33 @@ interface IAppSearchManager {
in String packageName,
in String databaseName,
in String namespace,
in String uri,
in long usageTimeMillis,
in String id,
in long usageTimestampMillis,
in boolean systemUsage,
in int userId,
in IAppSearchResultCallback callback);
/**
* Removes documents by URI.
* Removes documents by ID.
*
* @param packageName The name of the package the document is in.
* @param databaseName The databaseName the document is in.
* @param namespace Namespace of the document to remove.
* @param uris The URIs of the documents to delete
* @param ids The IDs of the documents to delete
* @param userId Id of the calling user
* @param callback
* If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError}
* will be called with the cause throwable. Otherwise,
* {@link IAppSearchBatchResultCallback#onResult} will be called with an
* {@link AppSearchBatchResult}&lt;{@link String}, {@link Void}&gt;
* where the keys are document URIs. If a document doesn't exist, it will be reported as a
* where the keys are document IDs. If a document doesn't exist, it will be reported as a
* failure where the {@code throwable} is {@code null}.
*/
void removeByUri(
void removeByDocumentId(
in String packageName,
in String databaseName,
in String namespace,
in List<String> uris,
in List<String> ids,
in int userId,
in IAppSearchBatchResultCallback callback);

View File

@@ -156,10 +156,10 @@ public class AppSearchEmail extends GenericDocument {
* Creates a new {@link AppSearchEmail.Builder}
*
* @param namespace The namespace of the Email.
* @param uri The Uri of the Email.
* @param id The ID of the Email.
*/
public Builder(@NonNull String namespace, @NonNull String uri) {
super(namespace, uri, SCHEMA_TYPE);
public Builder(@NonNull String namespace, @NonNull String id) {
super(namespace, id, SCHEMA_TYPE);
}
/** Sets the from address of {@link AppSearchEmail} */

View File

@@ -273,7 +273,7 @@ public final class AppSearchSchema {
* Returns the cardinality of the property (whether it is optional, required or repeated).
*/
public @Cardinality int getCardinality() {
return mBundle.getInt(CARDINALITY_FIELD, -1);
return mBundle.getInt(CARDINALITY_FIELD, CARDINALITY_OPTIONAL);
}
@Override
@@ -407,11 +407,7 @@ public final class AppSearchSchema {
return mBundle.getInt(TOKENIZER_TYPE_FIELD);
}
/**
* Builder for {@link StringPropertyConfig}.
*
* <p>{@link #setCardinality} must be called or {@link #build} will fail.
*/
/** Builder for {@link StringPropertyConfig}. */
public static final class Builder {
private final Bundle mBundle = new Bundle();
private boolean mBuilt = false;
@@ -420,12 +416,16 @@ public final class AppSearchSchema {
public Builder(@NonNull String propertyName) {
mBundle.putString(NAME_FIELD, propertyName);
mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_STRING);
mBundle.putInt(CARDINALITY_FIELD, CARDINALITY_OPTIONAL);
mBundle.putInt(INDEXING_TYPE_FIELD, INDEXING_TYPE_NONE);
mBundle.putInt(TOKENIZER_TYPE_FIELD, TOKENIZER_TYPE_NONE);
}
/**
* The cardinality of the property (whether it is optional, required or repeated).
*
* <p>This property must be set.
* <p>If this method is not called, the default cardinality is {@link
* PropertyConfig#CARDINALITY_OPTIONAL}.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass
@NonNull
@@ -439,6 +439,9 @@ public final class AppSearchSchema {
/**
* Configures how a property should be indexed so that it can be retrieved by queries.
*
* <p>If this method is not called, the default indexing type is {@link
* StringPropertyConfig#INDEXING_TYPE_NONE}, so that it cannot be matched by queries.
*/
@NonNull
public StringPropertyConfig.Builder setIndexingType(@IndexingType int indexingType) {
@@ -449,7 +452,17 @@ public final class AppSearchSchema {
return this;
}
/** Configures how this property should be tokenized (split into words). */
/**
* Configures how this property should be tokenized (split into words).
*
* <p>If this method is not called, the default indexing type is {@link
* StringPropertyConfig#TOKENIZER_TYPE_NONE}, so that it is not tokenized.
*
* <p>This method must be called with a value other than {@link
* StringPropertyConfig#TOKENIZER_TYPE_NONE} if the property is indexed (i.e. if {@link
* #setIndexingType} has been called with a value other than {@link
* StringPropertyConfig#INDEXING_TYPE_NONE}).
*/
@NonNull
public StringPropertyConfig.Builder setTokenizerType(@TokenizerType int tokenizerType) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
@@ -464,16 +477,11 @@ public final class AppSearchSchema {
*
* <p>After calling this method, the builder must no longer be used.
*
* @throws IllegalSchemaException if the property is not correctly populated
* @throws IllegalStateException if the builder has already been used
*/
@NonNull
public StringPropertyConfig build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
// TODO(b/147692920): Send the schema to Icing Lib for official validation, instead
// of partially reimplementing some of the validation Icing does here.
if (!mBundle.containsKey(CARDINALITY_FIELD)) {
throw new IllegalSchemaException("Missing field: cardinality");
}
mBuilt = true;
return new StringPropertyConfig(mBundle);
}
@@ -486,11 +494,7 @@ public final class AppSearchSchema {
super(bundle);
}
/**
* Builder for {@link Int64PropertyConfig}.
*
* <p>{@link #setCardinality} must be called or {@link #build} will fail.
*/
/** Builder for {@link Int64PropertyConfig}. */
public static final class Builder {
private final Bundle mBundle = new Bundle();
private boolean mBuilt = false;
@@ -499,12 +503,14 @@ public final class AppSearchSchema {
public Builder(@NonNull String propertyName) {
mBundle.putString(NAME_FIELD, propertyName);
mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_INT64);
mBundle.putInt(CARDINALITY_FIELD, CARDINALITY_OPTIONAL);
}
/**
* The cardinality of the property (whether it is optional, required or repeated).
*
* <p>This property must be set.
* <p>If this method is not called, the default cardinality is {@link
* PropertyConfig#CARDINALITY_OPTIONAL}.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass
@NonNull
@@ -521,14 +527,11 @@ public final class AppSearchSchema {
*
* <p>After calling this method, the builder must no longer be used.
*
* @throws IllegalSchemaException if the property is not correctly populated
* @throws IllegalStateException if the builder has already been used
*/
@NonNull
public Int64PropertyConfig build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
if (!mBundle.containsKey(CARDINALITY_FIELD)) {
throw new IllegalSchemaException("Missing field: cardinality");
}
mBuilt = true;
return new Int64PropertyConfig(mBundle);
}
@@ -541,11 +544,7 @@ public final class AppSearchSchema {
super(bundle);
}
/**
* Builder for {@link DoublePropertyConfig}.
*
* <p>{@link #setCardinality} must be called or {@link #build} will fail.
*/
/** Builder for {@link DoublePropertyConfig}. */
public static final class Builder {
private final Bundle mBundle = new Bundle();
private boolean mBuilt = false;
@@ -554,12 +553,14 @@ public final class AppSearchSchema {
public Builder(@NonNull String propertyName) {
mBundle.putString(NAME_FIELD, propertyName);
mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_DOUBLE);
mBundle.putInt(CARDINALITY_FIELD, CARDINALITY_OPTIONAL);
}
/**
* The cardinality of the property (whether it is optional, required or repeated).
*
* <p>This property must be set.
* <p>If this method is not called, the default cardinality is {@link
* PropertyConfig#CARDINALITY_OPTIONAL}.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass
@NonNull
@@ -576,14 +577,11 @@ public final class AppSearchSchema {
*
* <p>After calling this method, the builder must no longer be used.
*
* @throws IllegalSchemaException if the property is not correctly populated
* @throws IllegalStateException if the builder has already been used
*/
@NonNull
public DoublePropertyConfig build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
if (!mBundle.containsKey(CARDINALITY_FIELD)) {
throw new IllegalSchemaException("Missing field: cardinality");
}
mBuilt = true;
return new DoublePropertyConfig(mBundle);
}
@@ -596,11 +594,7 @@ public final class AppSearchSchema {
super(bundle);
}
/**
* Builder for {@link BooleanPropertyConfig}.
*
* <p>{@link #setCardinality} must be called or {@link #build} will fail.
*/
/** Builder for {@link BooleanPropertyConfig}. */
public static final class Builder {
private final Bundle mBundle = new Bundle();
private boolean mBuilt = false;
@@ -609,12 +603,14 @@ public final class AppSearchSchema {
public Builder(@NonNull String propertyName) {
mBundle.putString(NAME_FIELD, propertyName);
mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_BOOLEAN);
mBundle.putInt(CARDINALITY_FIELD, CARDINALITY_OPTIONAL);
}
/**
* The cardinality of the property (whether it is optional, required or repeated).
*
* <p>This property must be set.
* <p>If this method is not called, the default cardinality is {@link
* PropertyConfig#CARDINALITY_OPTIONAL}.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass
@NonNull
@@ -631,14 +627,11 @@ public final class AppSearchSchema {
*
* <p>After calling this method, the builder must no longer be used.
*
* @throws IllegalSchemaException if the property is not correctly populated
* @throws IllegalStateException if the builder has already been used
*/
@NonNull
public BooleanPropertyConfig build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
if (!mBundle.containsKey(CARDINALITY_FIELD)) {
throw new IllegalSchemaException("Missing field: cardinality");
}
mBuilt = true;
return new BooleanPropertyConfig(mBundle);
}
@@ -651,11 +644,7 @@ public final class AppSearchSchema {
super(bundle);
}
/**
* Builder for {@link BytesPropertyConfig}.
*
* <p>{@link #setCardinality} must be called or {@link #build} will fail.
*/
/** Builder for {@link BytesPropertyConfig}. */
public static final class Builder {
private final Bundle mBundle = new Bundle();
private boolean mBuilt = false;
@@ -664,12 +653,14 @@ public final class AppSearchSchema {
public Builder(@NonNull String propertyName) {
mBundle.putString(NAME_FIELD, propertyName);
mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_BYTES);
mBundle.putInt(CARDINALITY_FIELD, CARDINALITY_OPTIONAL);
}
/**
* The cardinality of the property (whether it is optional, required or repeated).
*
* <p>This property must be set.
* <p>If this method is not called, the default cardinality is {@link
* PropertyConfig#CARDINALITY_OPTIONAL}.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass
@NonNull
@@ -686,14 +677,11 @@ public final class AppSearchSchema {
*
* <p>After calling this method, the builder must no longer be used.
*
* @throws IllegalSchemaException if the property is not correctly populated
* @throws IllegalStateException if the builder has already been used
*/
@NonNull
public BytesPropertyConfig build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
if (!mBundle.containsKey(CARDINALITY_FIELD)) {
throw new IllegalSchemaException("Missing field: cardinality");
}
mBuilt = true;
return new BytesPropertyConfig(mBundle);
}
@@ -722,7 +710,7 @@ public final class AppSearchSchema {
* <p>If false, the nested document's properties are not indexed regardless of its own
* schema.
*/
public boolean isIndexNestedProperties() {
public boolean shouldIndexNestedProperties() {
return mBundle.getBoolean(INDEX_NESTED_PROPERTIES_FIELD);
}
@@ -741,29 +729,28 @@ public final class AppSearchSchema {
private final Bundle mBundle = new Bundle();
private boolean mBuilt = false;
/** Creates a new {@link DocumentPropertyConfig.Builder}. */
public Builder(@NonNull String propertyName) {
/**
* Creates a new {@link DocumentPropertyConfig.Builder}.
*
* @param propertyName The logical name of the property in the schema, which will be
* used as the key for this property in {@link
* GenericDocument.Builder#setPropertyDocument}.
* @param schemaType The type of documents which will be stored in this property.
* Documents of different types cannot be mixed into a single property.
*/
public Builder(@NonNull String propertyName, @NonNull String schemaType) {
mBundle.putString(NAME_FIELD, propertyName);
mBundle.putInt(DATA_TYPE_FIELD, DATA_TYPE_DOCUMENT);
}
/**
* The logical schema-type of the contents of this property.
*
* <p>This property must be set.
*/
@NonNull
public DocumentPropertyConfig.Builder setSchemaType(@NonNull String schemaType) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Objects.requireNonNull(schemaType);
mBundle.putInt(CARDINALITY_FIELD, CARDINALITY_OPTIONAL);
mBundle.putBoolean(INDEX_NESTED_PROPERTIES_FIELD, false);
mBundle.putString(SCHEMA_TYPE_FIELD, schemaType);
return this;
}
/**
* The cardinality of the property (whether it is optional, required or repeated).
*
* <p>This property must be set.
* <p>If this method is not called, the default cardinality is {@link
* PropertyConfig#CARDINALITY_OPTIONAL}.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // getter defined in superclass
@NonNull
@@ -783,7 +770,7 @@ public final class AppSearchSchema {
* schema.
*/
@NonNull
public DocumentPropertyConfig.Builder setIndexNestedProperties(
public DocumentPropertyConfig.Builder setShouldIndexNestedProperties(
boolean indexNestedProperties) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
mBundle.putBoolean(INDEX_NESTED_PROPERTIES_FIELD, indexNestedProperties);
@@ -795,18 +782,12 @@ public final class AppSearchSchema {
*
* <p>After calling this method, the builder must no longer be used.
*
* @throws IllegalSchemaException If the property is not correctly populated (e.g.
* missing {@code dataType}).
* @throws IllegalStateException if the builder has already been used (e.g. missing
* {@code dataType}).
*/
@NonNull
public DocumentPropertyConfig build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
if (mBundle.getString(SCHEMA_TYPE_FIELD, "").isEmpty()) {
throw new IllegalSchemaException("Missing field: schemaType");
}
if (!mBundle.containsKey(CARDINALITY_FIELD)) {
throw new IllegalSchemaException("Missing field: cardinality");
}
mBuilt = true;
return new DocumentPropertyConfig(mBundle);
}

View File

@@ -32,29 +32,29 @@ import java.util.Objects;
import java.util.Set;
/**
* Encapsulates a request to retrieve documents by namespace and URIs from the {@link
* Encapsulates a request to retrieve documents by namespace and IDs from the {@link
* AppSearchSession} database.
*
* @see AppSearchSession#getByUri
* @see AppSearchSession#getByDocumentId
*/
public final class GetByUriRequest {
public final class GetByDocumentIdRequest {
/**
* Schema type to be used in {@link android.app.appsearch.GetByUriRequest.Builder#addProjection}
* to apply property paths to all results, excepting any types that have had their own, specific
* property paths set.
* Schema type to be used in {@link GetByDocumentIdRequest.Builder#addProjection} to apply
* property paths to all results, excepting any types that have had their own, specific property
* paths set.
*/
public static final String PROJECTION_SCHEMA_TYPE_WILDCARD = "*";
private final String mNamespace;
private final Set<String> mUris;
private final Set<String> mIds;
private final Map<String, List<String>> mTypePropertyPathsMap;
GetByUriRequest(
GetByDocumentIdRequest(
@NonNull String namespace,
@NonNull Set<String> uris,
@NonNull Set<String> ids,
@NonNull Map<String, List<String>> typePropertyPathsMap) {
mNamespace = Objects.requireNonNull(namespace);
mUris = Objects.requireNonNull(uris);
mIds = Objects.requireNonNull(ids);
mTypePropertyPathsMap = Objects.requireNonNull(typePropertyPathsMap);
}
@@ -64,10 +64,10 @@ public final class GetByUriRequest {
return mNamespace;
}
/** Returns the set of URIs attached to the request. */
/** Returns the set of document IDs attached to the request. */
@NonNull
public Set<String> getUris() {
return Collections.unmodifiableSet(mUris);
public Set<String> getIds() {
return Collections.unmodifiableSet(mIds);
}
/**
@@ -81,8 +81,8 @@ public final class GetByUriRequest {
@NonNull
public Map<String, List<String>> getProjections() {
Map<String, List<String>> copy = new ArrayMap<>();
for (String key : mTypePropertyPathsMap.keySet()) {
copy.put(key, new ArrayList<>(mTypePropertyPathsMap.get(key)));
for (Map.Entry<String, List<String>> entry : mTypePropertyPathsMap.entrySet()) {
copy.put(entry.getKey(), new ArrayList<>(entry.getValue()));
}
return copy;
}
@@ -103,42 +103,42 @@ public final class GetByUriRequest {
}
/**
* Builder for {@link GetByUriRequest} objects.
* Builder for {@link GetByDocumentIdRequest} objects.
*
* <p>Once {@link #build} is called, the instance can no longer be used.
*/
public static final class Builder {
private final String mNamespace;
private final Set<String> mUris = new ArraySet<>();
private final Set<String> mIds = new ArraySet<>();
private final Map<String, List<String>> mProjectionTypePropertyPaths = new ArrayMap<>();
private boolean mBuilt = false;
/** Creates a {@link GetByUriRequest.Builder} instance. */
/** Creates a {@link GetByDocumentIdRequest.Builder} instance. */
public Builder(@NonNull String namespace) {
mNamespace = Objects.requireNonNull(namespace);
}
/**
* Adds one or more URIs to the request.
* Adds one or more document IDs to the request.
*
* @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public Builder addUris(@NonNull String... uris) {
Objects.requireNonNull(uris);
return addUris(Arrays.asList(uris));
public Builder addIds(@NonNull String... ids) {
Objects.requireNonNull(ids);
return addIds(Arrays.asList(ids));
}
/**
* Adds a collection of URIs to the request.
* Adds a collection of IDs to the request.
*
* @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public Builder addUris(@NonNull Collection<String> uris) {
public Builder addIds(@NonNull Collection<String> ids) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Objects.requireNonNull(uris);
mUris.addAll(uris);
Objects.requireNonNull(ids);
mIds.addAll(ids);
return this;
}
@@ -152,8 +152,9 @@ public final class GetByUriRequest {
* of that type will be retrieved.
*
* <p>If property path is added for the {@link
* GetByUriRequest#PROJECTION_SCHEMA_TYPE_WILDCARD}, then those property paths will apply to
* all results, excepting any types that have their own, specific property paths set.
* GetByDocumentIdRequest#PROJECTION_SCHEMA_TYPE_WILDCARD}, then those property paths will
* apply to all results, excepting any types that have their own, specific property paths
* set.
*
* @throws IllegalStateException if the builder has already been used.
* @see SearchSpec.Builder#addProjection
@@ -174,15 +175,15 @@ public final class GetByUriRequest {
}
/**
* Builds a new {@link GetByUriRequest}.
* Builds a new {@link GetByDocumentIdRequest}.
*
* @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public GetByUriRequest build() {
public GetByDocumentIdRequest build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
mBuilt = true;
return new GetByUriRequest(mNamespace, mUris, mProjectionTypePropertyPaths);
return new GetByDocumentIdRequest(mNamespace, mIds, mProjectionTypePropertyPaths);
}
}
}

View File

@@ -75,7 +75,7 @@ public class GetSchemaResponse {
/** Builder for {@link GetSchemaResponse} objects. */
public static final class Builder {
private int mVersion;
private int mVersion = 0;
private boolean mBuilt = false;
private final ArrayList<Bundle> mSchemaBundles = new ArrayList<>();

View File

@@ -52,7 +52,7 @@ public abstract class Migrator {
*
* <p>If this {@link Migrator} is provided to cover a compatible schema change via {@link
* AppSearchSession#setSchema}, documents under the old version won't be removed unless you use
* the same URI.
* the same document ID.
*
* <p>This method will be invoked on the background worker thread provided via {@link
* AppSearchSession#setSchema}.
@@ -75,7 +75,7 @@ public abstract class Migrator {
*
* <p>If this {@link Migrator} is provided to cover a compatible schema change via {@link
* AppSearchSession#setSchema}, documents under the old version won't be removed unless you use
* the same URI.
* the same document ID.
*
* <p>This method will be invoked on the background worker thread.
*

View File

@@ -28,18 +28,18 @@ import java.util.Objects;
import java.util.Set;
/**
* Encapsulates a request to remove documents by namespace and URIs from the {@link
* AppSearchSession} database.
* Encapsulates a request to remove documents by namespace and IDs from the {@link AppSearchSession}
* database.
*
* @see AppSearchSession#remove
*/
public final class RemoveByUriRequest {
public final class RemoveByDocumentIdRequest {
private final String mNamespace;
private final Set<String> mUris;
private final Set<String> mIds;
RemoveByUriRequest(String namespace, Set<String> uris) {
RemoveByDocumentIdRequest(String namespace, Set<String> ids) {
mNamespace = namespace;
mUris = uris;
mIds = ids;
}
/** Returns the namespace to remove documents from. */
@@ -48,61 +48,61 @@ public final class RemoveByUriRequest {
return mNamespace;
}
/** Returns the set of URIs attached to the request. */
/** Returns the set of document IDs attached to the request. */
@NonNull
public Set<String> getUris() {
return Collections.unmodifiableSet(mUris);
public Set<String> getIds() {
return Collections.unmodifiableSet(mIds);
}
/**
* Builder for {@link RemoveByUriRequest} objects.
* Builder for {@link RemoveByDocumentIdRequest} objects.
*
* <p>Once {@link #build} is called, the instance can no longer be used.
*/
public static final class Builder {
private final String mNamespace;
private final Set<String> mUris = new ArraySet<>();
private final Set<String> mIds = new ArraySet<>();
private boolean mBuilt = false;
/** Creates a {@link RemoveByUriRequest.Builder} instance. */
/** Creates a {@link RemoveByDocumentIdRequest.Builder} instance. */
public Builder(@NonNull String namespace) {
mNamespace = Objects.requireNonNull(namespace);
}
/**
* Adds one or more URIs to the request.
* Adds one or more document IDs to the request.
*
* @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public Builder addUris(@NonNull String... uris) {
Objects.requireNonNull(uris);
return addUris(Arrays.asList(uris));
public Builder addIds(@NonNull String... ids) {
Objects.requireNonNull(ids);
return addIds(Arrays.asList(ids));
}
/**
* Adds a collection of URIs to the request.
* Adds a collection of IDs to the request.
*
* @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public Builder addUris(@NonNull Collection<String> uris) {
public Builder addIds(@NonNull Collection<String> ids) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Objects.requireNonNull(uris);
mUris.addAll(uris);
Objects.requireNonNull(ids);
mIds.addAll(ids);
return this;
}
/**
* Builds a new {@link RemoveByUriRequest}.
* Builds a new {@link RemoveByDocumentIdRequest}.
*
* @throws IllegalStateException if the builder has already been used.
*/
@NonNull
public RemoveByUriRequest build() {
public RemoveByDocumentIdRequest build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
mBuilt = true;
return new RemoveByUriRequest(mNamespace, mUris);
return new RemoveByDocumentIdRequest(mNamespace, mIds);
}
}
}

View File

@@ -16,6 +16,7 @@
package android.app.appsearch;
import android.annotation.CurrentTimeMillisLong;
import android.annotation.NonNull;
import com.android.internal.util.Preconditions;
@@ -35,20 +36,20 @@ public final class ReportSystemUsageRequest {
private final String mPackageName;
private final String mDatabase;
private final String mNamespace;
private final String mUri;
private final long mUsageTimeMillis;
private final String mDocumentId;
private final long mUsageTimestampMillis;
ReportSystemUsageRequest(
@NonNull String packageName,
@NonNull String database,
@NonNull String namespace,
@NonNull String uri,
long usageTimeMillis) {
@NonNull String documentId,
long usageTimestampMillis) {
mPackageName = Objects.requireNonNull(packageName);
mDatabase = Objects.requireNonNull(database);
mNamespace = Objects.requireNonNull(namespace);
mUri = Objects.requireNonNull(uri);
mUsageTimeMillis = usageTimeMillis;
mDocumentId = Objects.requireNonNull(documentId);
mUsageTimestampMillis = usageTimestampMillis;
}
/** Returns the package name of the app which owns the document that was used. */
@@ -69,10 +70,10 @@ public final class ReportSystemUsageRequest {
return mNamespace;
}
/** Returns the URI of document that was used. */
/** Returns the ID of document that was used. */
@NonNull
public String getUri() {
return mUri;
public String getDocumentId() {
return mDocumentId;
}
/**
@@ -81,8 +82,9 @@ public final class ReportSystemUsageRequest {
*
* <p>The value is in the {@link System#currentTimeMillis} time base.
*/
public long getUsageTimeMillis() {
return mUsageTimeMillis;
@CurrentTimeMillisLong
public long getUsageTimestampMillis() {
return mUsageTimestampMillis;
}
/** Builder for {@link ReportSystemUsageRequest} objects. */
@@ -90,31 +92,20 @@ public final class ReportSystemUsageRequest {
private final String mPackageName;
private final String mDatabase;
private final String mNamespace;
private String mUri;
private Long mUsageTimeMillis;
private final String mDocumentId;
private Long mUsageTimestampMillis;
private boolean mBuilt = false;
/** Creates a {@link ReportSystemUsageRequest.Builder} instance. */
public Builder(
@NonNull String packageName, @NonNull String database, @NonNull String namespace) {
@NonNull String packageName,
@NonNull String database,
@NonNull String namespace,
@NonNull String documentId) {
mPackageName = Objects.requireNonNull(packageName);
mDatabase = Objects.requireNonNull(database);
mNamespace = Objects.requireNonNull(namespace);
}
/**
* Sets the URI of the document being used.
*
* <p>This field is required.
*
* @throws IllegalStateException if the builder has already been used
*/
@NonNull
public ReportSystemUsageRequest.Builder setUri(@NonNull String uri) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Objects.requireNonNull(uri);
mUri = uri;
return this;
mDocumentId = Objects.requireNonNull(documentId);
}
/**
@@ -129,28 +120,27 @@ public final class ReportSystemUsageRequest {
* @throws IllegalStateException if the builder has already been used
*/
@NonNull
public ReportSystemUsageRequest.Builder setUsageTimeMillis(long usageTimeMillis) {
public ReportSystemUsageRequest.Builder setUsageTimestampMillis(
@CurrentTimeMillisLong long usageTimestampMillis) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
mUsageTimeMillis = usageTimeMillis;
mUsageTimestampMillis = usageTimestampMillis;
return this;
}
/**
* Builds a new {@link ReportSystemUsageRequest}.
*
* @throws NullPointerException if {@link #setUri} has never been called
* @throws IllegalStateException if the builder has already been used
*/
@NonNull
public ReportSystemUsageRequest build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Objects.requireNonNull(mUri, "ReportUsageRequest is missing a URI");
if (mUsageTimeMillis == null) {
mUsageTimeMillis = System.currentTimeMillis();
if (mUsageTimestampMillis == null) {
mUsageTimestampMillis = System.currentTimeMillis();
}
mBuilt = true;
return new ReportSystemUsageRequest(
mPackageName, mDatabase, mNamespace, mUri, mUsageTimeMillis);
mPackageName, mDatabase, mNamespace, mDocumentId, mUsageTimestampMillis);
}
}
}

View File

@@ -16,6 +16,7 @@
package android.app.appsearch;
import android.annotation.CurrentTimeMillisLong;
import android.annotation.NonNull;
import com.android.internal.util.Preconditions;
@@ -31,13 +32,14 @@ import java.util.Objects;
*/
public final class ReportUsageRequest {
private final String mNamespace;
private final String mUri;
private final long mUsageTimeMillis;
private final String mDocumentId;
private final long mUsageTimestampMillis;
ReportUsageRequest(@NonNull String namespace, @NonNull String uri, long usageTimeMillis) {
ReportUsageRequest(
@NonNull String namespace, @NonNull String documentId, long usageTimestampMillis) {
mNamespace = Objects.requireNonNull(namespace);
mUri = Objects.requireNonNull(uri);
mUsageTimeMillis = usageTimeMillis;
mDocumentId = Objects.requireNonNull(documentId);
mUsageTimestampMillis = usageTimestampMillis;
}
/** Returns the namespace of the document that was used. */
@@ -46,10 +48,10 @@ public final class ReportUsageRequest {
return mNamespace;
}
/** Returns the URI of document that was used. */
/** Returns the ID of document that was used. */
@NonNull
public String getUri() {
return mUri;
public String getDocumentId() {
return mDocumentId;
}
/**
@@ -58,35 +60,22 @@ public final class ReportUsageRequest {
*
* <p>The value is in the {@link System#currentTimeMillis} time base.
*/
public long getUsageTimeMillis() {
return mUsageTimeMillis;
@CurrentTimeMillisLong
public long getUsageTimestampMillis() {
return mUsageTimestampMillis;
}
/** Builder for {@link ReportUsageRequest} objects. */
public static final class Builder {
private final String mNamespace;
private String mUri;
private Long mUsageTimeMillis;
private final String mDocumentId;
private Long mUsageTimestampMillis;
private boolean mBuilt = false;
/** Creates a {@link ReportUsageRequest.Builder} instance. */
public Builder(@NonNull String namespace) {
public Builder(@NonNull String namespace, @NonNull String documentId) {
mNamespace = Objects.requireNonNull(namespace);
}
/**
* Sets the URI of the document being used.
*
* <p>This field is required.
*
* @throws IllegalStateException if the builder has already been used
*/
@NonNull
public ReportUsageRequest.Builder setUri(@NonNull String uri) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Objects.requireNonNull(uri);
mUri = uri;
return this;
mDocumentId = Objects.requireNonNull(documentId);
}
/**
@@ -101,27 +90,26 @@ public final class ReportUsageRequest {
* @throws IllegalStateException if the builder has already been used
*/
@NonNull
public ReportUsageRequest.Builder setUsageTimeMillis(long usageTimeMillis) {
public ReportUsageRequest.Builder setUsageTimestampMillis(
@CurrentTimeMillisLong long usageTimestampMillis) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
mUsageTimeMillis = usageTimeMillis;
mUsageTimestampMillis = usageTimestampMillis;
return this;
}
/**
* Builds a new {@link ReportUsageRequest}.
*
* @throws NullPointerException if {@link #setUri} has never been called
* @throws IllegalStateException if the builder has already been used
*/
@NonNull
public ReportUsageRequest build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Objects.requireNonNull(mUri, "ReportUsageRequest is missing a URI");
if (mUsageTimeMillis == null) {
mUsageTimeMillis = System.currentTimeMillis();
if (mUsageTimestampMillis == null) {
mUsageTimestampMillis = System.currentTimeMillis();
}
mBuilt = true;
return new ReportUsageRequest(mNamespace, mUri, mUsageTimeMillis);
return new ReportUsageRequest(mNamespace, mDocumentId, mUsageTimestampMillis);
}
}
}

View File

@@ -415,16 +415,13 @@ public final class SearchResult {
private static String getPropertyValues(GenericDocument document, String propertyName) {
// In IcingLib snippeting is available for only 3 data types i.e String, double and
// long, so we need to check which of these three are requested.
// TODO (tytytyww): getPropertyStringArray takes property name, handle for property
// path.
// TODO (tytytyww): support double[] and long[].
String[] values = document.getPropertyStringArray(propertyName);
if (values == null) {
throw new IllegalStateException("No content found for requested property path!");
String result = document.getPropertyString(propertyName);
if (result == null) {
throw new IllegalStateException(
"No content found for requested property path: " + propertyName);
}
// TODO(b/175146044): Return the proper match based on the index in the propertyName.
return values[0];
return result;
}
/** Builder for {@link MatchInfo} objects. */
@@ -433,23 +430,22 @@ public final class SearchResult {
private boolean mBuilt = false;
/**
* Sets the property path corresponding to the given entry.
* Creates a new {@link MatchInfo.Builder} reporting a match with the given property
* path.
*
* <p>A property path is a '.' - delimited sequence of property names indicating which
* <p>A property path is a dot-delimited sequence of property names indicating which
* property in the document these snippets correspond to.
*
* <p>Example properties: 'body', 'sender.name', 'sender.emailaddress', etc. For class
* example 1 this returns "subject"
* <p>Example properties: 'body', 'sender.name', 'sender.emailaddress', etc.
* For class example 1 this returns "subject".
*
* @throws IllegalStateException if the builder has already been used
* @param propertyPath A {@code dot-delimited sequence of property names indicating
* which property in the document these snippets correspond to.
*/
@NonNull
public Builder setPropertyPath(@NonNull String propertyPath) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
public Builder(@NonNull String propertyPath) {
mBundle.putString(
SearchResult.MatchInfo.PROPERTY_PATH_FIELD,
Objects.requireNonNull(propertyPath));
return this;
}
/**

View File

@@ -20,7 +20,6 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.app.appsearch.exceptions.IllegalSearchSpecException;
import android.os.Bundle;
import android.util.ArrayMap;
@@ -323,9 +322,15 @@ public final class SearchSpec {
public Builder() {
mBundle = new Bundle();
mBundle.putInt(NUM_PER_PAGE_FIELD, DEFAULT_NUM_PER_PAGE);
mBundle.putInt(TERM_MATCH_TYPE_FIELD, TERM_MATCH_PREFIX);
}
/** Indicates how the query terms should match {@code TermMatchCode} in the index. */
/**
* Indicates how the query terms should match {@code TermMatchCode} in the index.
*
* <p>If this method is not called, the default term match type is {@link
* SearchSpec#TERM_MATCH_PREFIX}.
*/
@NonNull
public Builder setTermMatch(@TermMatch int termMatchTypeCode) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
@@ -634,9 +639,6 @@ public final class SearchSpec {
@NonNull
public SearchSpec build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
if (!mBundle.containsKey(TERM_MATCH_TYPE_FIELD)) {
throw new IllegalSearchSpecException("Missing termMatchType field.");
}
mBundle.putStringArrayList(NAMESPACE_FIELD, mNamespaces);
mBundle.putStringArrayList(SCHEMA_FIELD, mSchemas);
mBundle.putStringArrayList(PACKAGE_NAME_FIELD, mPackageNames);

View File

@@ -414,7 +414,6 @@ public final class SetSchemaRequest {
@NonNull
public SetSchemaRequest build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
mBuilt = true;
// Verify that any schema types with display or visibility settings refer to a real
// schema.
@@ -432,6 +431,7 @@ public final class SetSchemaRequest {
"Schema types " + referencedSchemas + " referenced, but were not added.");
}
mBuilt = true;
return new SetSchemaRequest(
mSchemas,
mSchemasNotDisplayedBySystem,

View File

@@ -86,7 +86,7 @@ public class SetSchemaResponse {
* <p>A {@link MigrationFailure} will be generated if the system trying to save a post-migrated
* {@link GenericDocument} but fail.
*
* <p>{@link MigrationFailure} contains the uri, namespace and schemaType of the post-migrated
* <p>{@link MigrationFailure} contains the namespace, id and schemaType of the post-migrated
* {@link GenericDocument} and the error reason. Mostly it will be mismatch the schema it
* migrated to.
*/
@@ -257,14 +257,40 @@ public class SetSchemaResponse {
public static class MigrationFailure {
private static final String SCHEMA_TYPE_FIELD = "schemaType";
private static final String NAMESPACE_FIELD = "namespace";
private static final String URI_FIELD = "uri";
private static final String DOCUMENT_ID_FIELD = "id";
private static final String ERROR_MESSAGE_FIELD = "errorMessage";
private static final String RESULT_CODE_FIELD = "resultCode";
private final Bundle mBundle;
/**
* Constructs a new {@link MigrationFailure}.
*
* @param namespace The namespace of the document which failed to be migrated.
* @param documentId The id of the document which failed to be migrated.
* @param schemaType The type of the document which failed to be migrated.
* @param failedResult The reason why the document failed to be indexed.
* @throws IllegalArgumentException if the provided {@code failedResult} was not a failure.
*/
public MigrationFailure(
@NonNull String namespace,
@NonNull String documentId,
@NonNull String schemaType,
@NonNull AppSearchResult<?> failedResult) {
mBundle = new Bundle();
mBundle.putString(NAMESPACE_FIELD, Objects.requireNonNull(namespace));
mBundle.putString(DOCUMENT_ID_FIELD, Objects.requireNonNull(documentId));
mBundle.putString(SCHEMA_TYPE_FIELD, Objects.requireNonNull(schemaType));
Objects.requireNonNull(failedResult);
Preconditions.checkArgument(
!failedResult.isSuccess(), "failedResult was actually successful");
mBundle.putString(ERROR_MESSAGE_FIELD, failedResult.getErrorMessage());
mBundle.putInt(RESULT_CODE_FIELD, failedResult.getResultCode());
}
MigrationFailure(@NonNull Bundle bundle) {
mBundle = bundle;
mBundle = Objects.requireNonNull(bundle);
}
/**
@@ -277,27 +303,27 @@ public class SetSchemaResponse {
return mBundle;
}
/** Returns the schema type of the {@link GenericDocument} that fails to be migrated. */
@NonNull
public String getSchemaType() {
return mBundle.getString(SCHEMA_TYPE_FIELD, /*defaultValue=*/ "");
}
/** Returns the namespace of the {@link GenericDocument} that fails to be migrated. */
/** Returns the namespace of the {@link GenericDocument} that failed to be migrated. */
@NonNull
public String getNamespace() {
return mBundle.getString(NAMESPACE_FIELD, /*defaultValue=*/ "");
}
/** Returns the uri of the {@link GenericDocument} that fails to be migrated. */
/** Returns the id of the {@link GenericDocument} that failed to be migrated. */
@NonNull
public String getUri() {
return mBundle.getString(URI_FIELD, /*defaultValue=*/ "");
public String getDocumentId() {
return mBundle.getString(DOCUMENT_ID_FIELD, /*defaultValue=*/ "");
}
/** Returns the schema type of the {@link GenericDocument} that failed to be migrated. */
@NonNull
public String getSchemaType() {
return mBundle.getString(SCHEMA_TYPE_FIELD, /*defaultValue=*/ "");
}
/**
* Returns the {@link AppSearchResult} that indicates why the post-migrated {@link
* GenericDocument} fails to be saved.
* Returns the {@link AppSearchResult} that indicates why the post-migration {@link
* GenericDocument} failed to be indexed.
*/
@NonNull
public AppSearchResult<Void> getAppSearchResult() {
@@ -305,61 +331,5 @@ public class SetSchemaResponse {
mBundle.getInt(RESULT_CODE_FIELD),
mBundle.getString(ERROR_MESSAGE_FIELD, /*defaultValue=*/ ""));
}
/** Builder for {@link MigrationFailure} objects. */
public static final class Builder {
private String mSchemaType;
private String mNamespace;
private String mUri;
private final Bundle mBundle = new Bundle();
private AppSearchResult<Void> mFailureResult;
private boolean mBuilt = false;
/** Sets the schema type for the {@link MigrationFailure}. */
@NonNull
public Builder setSchemaType(@NonNull String schemaType) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
mSchemaType = Objects.requireNonNull(schemaType);
return this;
}
/** Sets the namespace for the {@link MigrationFailure}. */
@NonNull
public Builder setNamespace(@NonNull String namespace) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
mNamespace = Objects.requireNonNull(namespace);
return this;
}
/** Sets the uri for the {@link MigrationFailure}. */
@NonNull
public Builder setUri(@NonNull String uri) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
mUri = Objects.requireNonNull(uri);
return this;
}
/** Sets the failure {@link AppSearchResult} for the {@link MigrationFailure}. */
@NonNull
public Builder setAppSearchResult(@NonNull AppSearchResult<Void> appSearchResult) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkState(!appSearchResult.isSuccess(), "Input a success result");
mFailureResult = Objects.requireNonNull(appSearchResult);
return this;
}
/** Builds a {@link MigrationFailure} object. */
@NonNull
public MigrationFailure build() {
Preconditions.checkState(!mBuilt, "Builder has already been used");
mBundle.putString(SCHEMA_TYPE_FIELD, mSchemaType);
mBundle.putString(NAMESPACE_FIELD, mNamespace);
mBundle.putString(URI_FIELD, mUri);
mBundle.putString(ERROR_MESSAGE_FIELD, mFailureResult.getErrorMessage());
mBundle.putInt(RESULT_CODE_FIELD, mFailureResult.getResultCode());
mBuilt = true;
return new MigrationFailure(mBundle);
}
}
}
}

View File

@@ -1,36 +0,0 @@
/*
* Copyright 2020 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 android.app.appsearch.exceptions;
import android.annotation.NonNull;
/**
* Indicates that a {@link android.app.appsearch.SearchResult} has logical inconsistencies such as
* unpopulated mandatory fields or illegal combinations of parameters.
*
* @hide
*/
public class IllegalSearchSpecException extends IllegalArgumentException {
/**
* Constructs a new {@link IllegalSearchSpecException}.
*
* @param message A developer-readable description of the issue with the bundle.
*/
public IllegalSearchSpecException(@NonNull String message) {
super(message);
}
}

View File

@@ -308,13 +308,13 @@ public class AppSearchManagerService extends SystemService {
GenericDocument document = new GenericDocument(documentBundles.get(i));
try {
impl.putDocument(packageName, databaseName, document, logger);
resultBuilder.setSuccess(document.getUri(), /*result=*/ null);
resultBuilder.setSuccess(document.getId(), /*result=*/ null);
++operationSuccessCount;
} catch (Throwable t) {
resultBuilder.setResult(document.getUri(),
resultBuilder.setResult(document.getId(),
throwableToFailedResult(t));
AppSearchResult<Void> result = throwableToFailedResult(t);
resultBuilder.setResult(document.getUri(), result);
resultBuilder.setResult(document.getId(), result);
// for failures, we would just log the one for last failure
statusCode = result.getResultCode();
++operationFailureCount;
@@ -354,14 +354,14 @@ public class AppSearchManagerService extends SystemService {
@NonNull String packageName,
@NonNull String databaseName,
@NonNull String namespace,
@NonNull List<String> uris,
@NonNull List<String> ids,
@NonNull Map<String, List<String>> typePropertyPaths,
@UserIdInt int userId,
@NonNull IAppSearchBatchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(namespace);
Objects.requireNonNull(uris);
Objects.requireNonNull(ids);
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
@@ -373,19 +373,19 @@ public class AppSearchManagerService extends SystemService {
new AppSearchBatchResult.Builder<>();
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
for (int i = 0; i < uris.size(); i++) {
String uri = uris.get(i);
for (int i = 0; i < ids.size(); i++) {
String id = ids.get(i);
try {
GenericDocument document =
impl.getDocument(
packageName,
databaseName,
namespace,
uri,
id,
typePropertyPaths);
resultBuilder.setSuccess(uri, document.getBundle());
resultBuilder.setSuccess(id, document.getBundle());
} catch (Throwable t) {
resultBuilder.setResult(uri, throwableToFailedResult(t));
resultBuilder.setResult(id, throwableToFailedResult(t));
}
}
invokeCallbackOnResult(callback, resultBuilder.build());
@@ -578,14 +578,12 @@ public class AppSearchManagerService extends SystemService {
impl.putDocument(packageName, databaseName, document,
/*logger=*/ null);
} catch (Throwable t) {
migrationFailureBundles.add(
new SetSchemaResponse.MigrationFailure.Builder()
.setNamespace(document.getNamespace())
.setSchemaType(document.getSchemaType())
.setUri(document.getUri())
.setAppSearchResult(AppSearchResult
.throwableToFailedResult(t))
.build().getBundle());
migrationFailureBundles.add(new SetSchemaResponse.MigrationFailure(
document.getNamespace(),
document.getId(),
document.getSchemaType(),
AppSearchResult.throwableToFailedResult(t))
.getBundle());
}
}
}
@@ -603,14 +601,14 @@ public class AppSearchManagerService extends SystemService {
@NonNull String packageName,
@NonNull String databaseName,
@NonNull String namespace,
@NonNull String uri,
@NonNull String documentId,
long usageTimeMillis,
boolean systemUsage,
@UserIdInt int userId,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(databaseName);
Objects.requireNonNull(namespace);
Objects.requireNonNull(uri);
Objects.requireNonNull(documentId);
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
@@ -625,7 +623,7 @@ public class AppSearchManagerService extends SystemService {
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
impl.reportUsage(
packageName, databaseName, namespace, uri,
packageName, databaseName, namespace, documentId,
usageTimeMillis, systemUsage);
invokeCallbackOnResult(
callback, AppSearchResult.newSuccessfulResult(/*result=*/ null));
@@ -636,16 +634,16 @@ public class AppSearchManagerService extends SystemService {
}
@Override
public void removeByUri(
public void removeByDocumentId(
@NonNull String packageName,
@NonNull String databaseName,
@NonNull String namespace,
@NonNull List<String> uris,
@NonNull List<String> ids,
@UserIdInt int userId,
@NonNull IAppSearchBatchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(uris);
Objects.requireNonNull(ids);
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
@@ -657,13 +655,13 @@ public class AppSearchManagerService extends SystemService {
new AppSearchBatchResult.Builder<>();
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
for (int i = 0; i < uris.size(); i++) {
String uri = uris.get(i);
for (int i = 0; i < ids.size(); i++) {
String id = ids.get(i);
try {
impl.remove(packageName, databaseName, namespace, uri);
resultBuilder.setSuccess(uri, /*result= */ null);
impl.remove(packageName, databaseName, namespace, id);
resultBuilder.setSuccess(id, /*result= */ null);
} catch (Throwable t) {
resultBuilder.setResult(uri, throwableToFailedResult(t));
resultBuilder.setResult(id, throwableToFailedResult(t));
}
}
// Now that the batch has been written. Persist the newly written data.

View File

@@ -103,14 +103,13 @@ public class VisibilityStore {
new AppSearchSchema.Builder(VISIBILITY_TYPE)
.addProperty(
new AppSearchSchema.StringPropertyConfig.Builder(
NOT_PLATFORM_SURFACEABLE_PROPERTY)
NOT_PLATFORM_SURFACEABLE_PROPERTY)
.setCardinality(
AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
.build())
.addProperty(
new AppSearchSchema.DocumentPropertyConfig.Builder(
PACKAGE_ACCESSIBLE_PROPERTY)
.setSchemaType(PACKAGE_ACCESSIBLE_TYPE)
PACKAGE_ACCESSIBLE_PROPERTY, PACKAGE_ACCESSIBLE_TYPE)
.setCardinality(
AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
.build())
@@ -160,9 +159,9 @@ public class VisibilityStore {
private static final String NAMESPACE = "";
/**
* Prefix to add to all visibility document uri's. IcingSearchEngine doesn't allow empty uri's.
* Prefix to add to all visibility document ids. IcingSearchEngine doesn't allow empty ids.
*/
private static final String URI_PREFIX = "uri:";
private static final String ID_PREFIX = "uri:";
private final AppSearchImpl mAppSearchImpl;
@@ -259,13 +258,13 @@ public class VisibilityStore {
}
try {
// Note: We use the other clients' prefixed names as uris
// Note: We use the other clients' prefixed names as ids
GenericDocument document =
mAppSearchImpl.getDocument(
PACKAGE_NAME,
DATABASE_NAME,
NAMESPACE,
/*uri=*/ addUriPrefix(prefix),
/*id=*/ addIdPrefix(prefix),
/*typePropertyPaths=*/ Collections.emptyMap());
// Update platform visibility settings
@@ -340,7 +339,7 @@ public class VisibilityStore {
// Persist the document
GenericDocument.Builder<?> visibilityDocument =
new GenericDocument.Builder<>(
NAMESPACE, /*uri=*/ addUriPrefix(prefix), VISIBILITY_TYPE);
NAMESPACE, /*id=*/ addIdPrefix(prefix), VISIBILITY_TYPE);
if (!schemasNotPlatformSurfaceable.isEmpty()) {
visibilityDocument.setPropertyString(
NOT_PLATFORM_SURFACEABLE_PROPERTY,
@@ -353,7 +352,7 @@ public class VisibilityStore {
schemasPackageAccessible.entrySet()) {
for (int i = 0; i < entry.getValue().size(); i++) {
GenericDocument packageAccessibleDocument = new GenericDocument.Builder<>(
NAMESPACE, /*uri=*/ "", PACKAGE_ACCESSIBLE_TYPE)
NAMESPACE, /*id=*/ "", PACKAGE_ACCESSIBLE_TYPE)
.setPropertyString(
PACKAGE_NAME_PROPERTY,
entry.getValue().get(i).getPackageName())
@@ -480,13 +479,13 @@ public class VisibilityStore {
}
/**
* Adds a uri prefix to create a visibility store document's uri.
* Adds a prefix to create a visibility store document's id.
*
* @param uri Non-prefixed uri
* @return Prefixed uri
* @param id Non-prefixed id
* @return Prefixed id
*/
private static String addUriPrefix(String uri) {
return URI_PREFIX + uri;
private static String addIdPrefix(String id) {
return ID_PREFIX + id;
}
/**

View File

@@ -30,7 +30,7 @@ import android.annotation.Nullable;
import android.annotation.WorkerThread;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.GetByUriRequest;
import android.app.appsearch.GetByDocumentIdRequest;
import android.app.appsearch.GetSchemaResponse;
import android.app.appsearch.PackageIdentifier;
import android.app.appsearch.SearchResultPage;
@@ -573,14 +573,14 @@ public final class AppSearchImpl implements Closeable {
}
/**
* Retrieves a document from the AppSearch index by URI.
* Retrieves a document from the AppSearch index by namespace and document ID.
*
* <p>This method belongs to query group.
*
* @param packageName The package that owns this document.
* @param databaseName The databaseName this document resides in.
* @param namespace The namespace this document resides in.
* @param uri The URI of the document to get.
* @param id The ID of the document to get.
* @param typePropertyPaths A map of schema type to a list of property paths to return in the
* result.
* @return The Document contents
@@ -591,7 +591,7 @@ public final class AppSearchImpl implements Closeable {
@NonNull String packageName,
@NonNull String databaseName,
@NonNull String namespace,
@NonNull String uri,
@NonNull String id,
@NonNull Map<String, List<String>> typePropertyPaths)
throws AppSearchException {
mReadWriteLock.readLock().lock();
@@ -606,7 +606,8 @@ public final class AppSearchImpl implements Closeable {
TypePropertyMask typePropertyMask = nonPrefixedPropertyMasks.get(i);
String nonPrefixedType = typePropertyMask.getSchemaType();
String prefixedType =
nonPrefixedType.equals(GetByUriRequest.PROJECTION_SCHEMA_TYPE_WILDCARD)
nonPrefixedType.equals(
GetByDocumentIdRequest.PROJECTION_SCHEMA_TYPE_WILDCARD)
? nonPrefixedType
: prefix + nonPrefixedType;
prefixedPropertyMasks.add(
@@ -618,7 +619,7 @@ public final class AppSearchImpl implements Closeable {
.build();
GetResultProto getResultProto =
mIcingSearchEngineLocked.get(prefix + namespace, uri, getResultSpec);
mIcingSearchEngineLocked.get(prefix + namespace, id, getResultSpec);
checkSuccess(getResultProto.getStatus());
// The schema type map cannot be null at this point. It could only be null if no
@@ -881,7 +882,7 @@ public final class AppSearchImpl implements Closeable {
@NonNull String packageName,
@NonNull String databaseName,
@NonNull String namespace,
@NonNull String uri,
@NonNull String documentId,
long usageTimestampMillis,
boolean systemUsage)
throws AppSearchException {
@@ -897,7 +898,7 @@ public final class AppSearchImpl implements Closeable {
UsageReport report =
UsageReport.newBuilder()
.setDocumentNamespace(prefixedNamespace)
.setDocumentUri(uri)
.setDocumentUri(documentId)
.setUsageTimestampMs(usageTimestampMillis)
.setUsageType(usageType)
.build();
@@ -910,21 +911,21 @@ public final class AppSearchImpl implements Closeable {
}
/**
* Removes the given document by URI.
* Removes the given document by id.
*
* <p>This method belongs to mutate group.
*
* @param packageName The package name that owns the document.
* @param databaseName The databaseName the document is in.
* @param namespace Namespace of the document to remove.
* @param uri URI of the document to remove.
* @param id ID of the document to remove.
* @throws AppSearchException on IcingSearchEngine error.
*/
public void remove(
@NonNull String packageName,
@NonNull String databaseName,
@NonNull String namespace,
@NonNull String uri)
@NonNull String id)
throws AppSearchException {
mReadWriteLock.writeLock().lock();
try {
@@ -932,7 +933,7 @@ public final class AppSearchImpl implements Closeable {
String prefixedNamespace = createPrefix(packageName, databaseName) + namespace;
DeleteResultProto deleteResultProto =
mIcingSearchEngineLocked.delete(prefixedNamespace, uri);
mIcingSearchEngineLocked.delete(prefixedNamespace, id);
checkSuccess(deleteResultProto.getStatus());
} finally {

View File

@@ -52,7 +52,7 @@ public final class GenericDocumentToProtoConverter {
Objects.requireNonNull(document);
DocumentProto.Builder mProtoBuilder = DocumentProto.newBuilder();
mProtoBuilder
.setUri(document.getUri())
.setUri(document.getId())
.setSchema(document.getSchemaType())
.setNamespace(document.getNamespace())
.setScore(document.getScore())

View File

@@ -104,7 +104,7 @@ public final class SchemaToProtoConverter {
.setDocumentIndexingConfig(
DocumentIndexingConfig.newBuilder()
.setIndexNestedProperties(
documentProperty.isIndexNestedProperties()));
documentProperty.shouldIndexNestedProperties()));
}
return builder.build();
}
@@ -174,10 +174,10 @@ public final class SchemaToProtoConverter {
@NonNull
private static AppSearchSchema.DocumentPropertyConfig toDocumentPropertyConfig(
@NonNull PropertyConfigProto proto) {
return new AppSearchSchema.DocumentPropertyConfig.Builder(proto.getPropertyName())
return new AppSearchSchema.DocumentPropertyConfig.Builder(
proto.getPropertyName(), proto.getSchemaType())
.setCardinality(proto.getCardinality().getNumber())
.setSchemaType(proto.getSchemaType())
.setIndexNestedProperties(
.setShouldIndexNestedProperties(
proto.getDocumentIndexingConfig().getIndexNestedProperties())
.build();
}

View File

@@ -125,8 +125,7 @@ public class SearchResultToProtoConverter {
private static SearchResult.MatchInfo toMatchInfo(
@NonNull SnippetMatchProto snippetMatchProto, @NonNull String propertyPath) {
return new SearchResult.MatchInfo.Builder()
.setPropertyPath(propertyPath)
return new SearchResult.MatchInfo.Builder(propertyPath)
.setExactMatchRange(
new SearchResult.MatchRange(
snippetMatchProto.getExactMatchPosition(),

View File

@@ -1 +1 @@
If9d1d770d2327d7d0db7d82acfc54787b5de64bc
I06df2c636d26419e653c5d8c9e7d15449da6816e

View File

@@ -24,10 +24,10 @@ import android.app.appsearch.AppSearchSession;
import android.app.appsearch.AppSearchSessionShim;
import android.app.appsearch.BatchResultCallback;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.GetByUriRequest;
import android.app.appsearch.GetByDocumentIdRequest;
import android.app.appsearch.GetSchemaResponse;
import android.app.appsearch.PutDocumentsRequest;
import android.app.appsearch.RemoveByUriRequest;
import android.app.appsearch.RemoveByDocumentIdRequest;
import android.app.appsearch.ReportUsageRequest;
import android.app.appsearch.SearchResults;
import android.app.appsearch.SearchResultsShim;
@@ -121,11 +121,12 @@ public class AppSearchSessionShimImpl implements AppSearchSessionShim {
@Override
@NonNull
public ListenableFuture<AppSearchBatchResult<String, GenericDocument>> getByUri(
@NonNull GetByUriRequest request) {
public ListenableFuture<AppSearchBatchResult<String, GenericDocument>> getByDocumentId(
@NonNull GetByDocumentIdRequest request) {
SettableFuture<AppSearchBatchResult<String, GenericDocument>> future =
SettableFuture.create();
mAppSearchSession.getByUri(request, mExecutor, new BatchResultCallbackAdapter<>(future));
mAppSearchSession.getByDocumentId(
request, mExecutor, new BatchResultCallbackAdapter<>(future));
return future;
}
@@ -148,7 +149,7 @@ public class AppSearchSessionShimImpl implements AppSearchSessionShim {
@Override
@NonNull
public ListenableFuture<AppSearchBatchResult<String, Void>> remove(
@NonNull RemoveByUriRequest request) {
@NonNull RemoveByDocumentIdRequest request) {
SettableFuture<AppSearchBatchResult<String, Void>> future = SettableFuture.create();
mAppSearchSession.remove(request, mExecutor, new BatchResultCallbackAdapter<>(future));
return future;

View File

@@ -25,10 +25,14 @@ import java.io.Closeable;
import java.util.Set;
/**
* Represents a connection to an AppSearch storage system where {@link GenericDocument}s can be
* placed and queried.
* Provides a connection to a single AppSearch database.
*
* <p>An {@link AppSearchSessionShim} instance provides access to database operations such as
* setting a schema, adding documents, and searching.
*
* <p>All implementations of this interface must be thread safe.
*
* @see GlobalSearchSessionShim
*/
public interface AppSearchSessionShim extends Closeable {
@@ -76,28 +80,29 @@ public interface AppSearchSessionShim extends Closeable {
*
* @param request containing documents to be indexed.
* @return a {@link ListenableFuture} which resolves to an {@link AppSearchBatchResult}. The
* keys of the returned {@link AppSearchBatchResult} are the URIs of the input documents.
* The values are either {@code null} if the corresponding document was successfully
* indexed, or a failed {@link AppSearchResult} otherwise.
* keys of the returned {@link AppSearchBatchResult} are the IDs of the input documents. The
* values are either {@code null} if the corresponding document was successfully indexed, or
* a failed {@link AppSearchResult} otherwise.
*/
@NonNull
ListenableFuture<AppSearchBatchResult<String, Void>> put(@NonNull PutDocumentsRequest request);
/**
* Gets {@link GenericDocument} objects by URIs and namespace from the {@link
* Gets {@link GenericDocument} objects by document IDs in a namespace from the {@link
* AppSearchSessionShim} database.
*
* @param request a request containing URIs and namespace to get documents for.
* @param request a request containing a namespace and IDs to get documents for.
* @return A {@link ListenableFuture} which resolves to an {@link AppSearchBatchResult}. The
* keys of the {@link AppSearchBatchResult} represent the input URIs from the {@link
* GetByUriRequest} object. The values are either the corresponding {@link GenericDocument}
* object for the URI on success, or an {@link AppSearchResult} object on failure. For
* example, if a URI is not found, the value for that URI will be set to an {@link
* AppSearchResult} object with result code: {@link AppSearchResult#RESULT_NOT_FOUND}.
* keys of the {@link AppSearchBatchResult} represent the input document IDs from the {@link
* GetByDocumentIdRequest} object. The values are either the corresponding {@link
* GenericDocument} object for the ID on success, or an {@link AppSearchResult} object on
* failure. For example, if an ID is not found, the value for that ID will be set to an
* {@link AppSearchResult} object with result code: {@link
* AppSearchResult#RESULT_NOT_FOUND}.
*/
@NonNull
ListenableFuture<AppSearchBatchResult<String, GenericDocument>> getByUri(
@NonNull GetByUriRequest request);
ListenableFuture<AppSearchBatchResult<String, GenericDocument>> getByDocumentId(
@NonNull GetByDocumentIdRequest request);
/**
* Retrieves documents from the open {@link AppSearchSessionShim} that match a given query
@@ -162,7 +167,7 @@ public interface AppSearchSessionShim extends Closeable {
SearchResultsShim search(@NonNull String queryExpression, @NonNull SearchSpec searchSpec);
/**
* Reports usage of a particular document by URI and namespace.
* Reports usage of a particular document by namespace and ID.
*
* <p>A usage report represents an event in which a user interacted with or viewed a document.
*
@@ -181,25 +186,26 @@ public interface AppSearchSessionShim extends Closeable {
ListenableFuture<Void> reportUsage(@NonNull ReportUsageRequest request);
/**
* Removes {@link GenericDocument} objects by URIs and namespace from the {@link
* Removes {@link GenericDocument} objects by document IDs in a namespace from the {@link
* AppSearchSessionShim} database.
*
* <p>Removed documents will no longer be surfaced by {@link #search} or {@link #getByUri}
* calls.
* <p>Removed documents will no longer be surfaced by {@link #search} or {@link
* #getByDocumentId} calls.
*
* <p>Once the database crosses the document count or byte usage threshold, removed documents
* will be deleted from disk.
*
* @param request {@link RemoveByUriRequest} with URIs and namespace to remove from the index.
* @param request {@link RemoveByDocumentIdRequest} with IDs in a namespace to remove from the
* index.
* @return a {@link ListenableFuture} which resolves to an {@link AppSearchBatchResult}. The
* keys of the {@link AppSearchBatchResult} represent the input URIs from the {@link
* RemoveByUriRequest} object. The values are either {@code null} on success, or a failed
* {@link AppSearchResult} otherwise. URIs that are not found will return a failed {@link
* AppSearchResult} with a result code of {@link AppSearchResult#RESULT_NOT_FOUND}.
* keys of the {@link AppSearchBatchResult} represent the input IDs from the {@link
* RemoveByDocumentIdRequest} object. The values are either {@code null} on success, or a
* failed {@link AppSearchResult} otherwise. IDs that are not found will return a failed
* {@link AppSearchResult} with a result code of {@link AppSearchResult#RESULT_NOT_FOUND}.
*/
@NonNull
ListenableFuture<AppSearchBatchResult<String, Void>> remove(
@NonNull RemoveByUriRequest request);
@NonNull RemoveByDocumentIdRequest request);
/**
* Removes {@link GenericDocument}s from the index by Query. Documents will be removed if they

View File

@@ -22,7 +22,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
import android.app.appsearch.AppSearchBatchResult;
import android.app.appsearch.AppSearchSessionShim;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.GetByUriRequest;
import android.app.appsearch.GetByDocumentIdRequest;
import android.app.appsearch.SearchResult;
import android.app.appsearch.SearchResultsShim;
@@ -43,30 +43,30 @@ public class AppSearchTestUtils {
}
public static List<GenericDocument> doGet(
AppSearchSessionShim session, String namespace, String... uris) throws Exception {
AppSearchSessionShim session, String namespace, String... ids) throws Exception {
AppSearchBatchResult<String, GenericDocument> result =
checkIsBatchResultSuccess(
session.getByUri(
new GetByUriRequest.Builder(namespace).addUris(uris).build()));
assertThat(result.getSuccesses()).hasSize(uris.length);
session.getByDocumentId(
new GetByDocumentIdRequest.Builder(namespace).addIds(ids).build()));
assertThat(result.getSuccesses()).hasSize(ids.length);
assertThat(result.getFailures()).isEmpty();
List<GenericDocument> list = new ArrayList<>(uris.length);
for (String uri : uris) {
list.add(result.getSuccesses().get(uri));
List<GenericDocument> list = new ArrayList<>(ids.length);
for (String id : ids) {
list.add(result.getSuccesses().get(id));
}
return list;
}
public static List<GenericDocument> doGet(AppSearchSessionShim session, GetByUriRequest request)
throws Exception {
public static List<GenericDocument> doGet(
AppSearchSessionShim session, GetByDocumentIdRequest request) throws Exception {
AppSearchBatchResult<String, GenericDocument> result =
checkIsBatchResultSuccess(session.getByUri(request));
Set<String> uris = request.getUris();
assertThat(result.getSuccesses()).hasSize(uris.size());
checkIsBatchResultSuccess(session.getByDocumentId(request));
Set<String> ids = request.getIds();
assertThat(result.getSuccesses()).hasSize(ids.size());
assertThat(result.getFailures()).isEmpty();
List<GenericDocument> list = new ArrayList<>(uris.size());
for (String uri : uris) {
list.add(result.getSuccesses().get(uri));
List<GenericDocument> list = new ArrayList<>(ids.size());
for (String id : ids) {
list.add(result.getSuccesses().get(id));
}
return list;
}

View File

@@ -23,9 +23,12 @@ import com.google.common.util.concurrent.ListenableFuture;
import java.io.Closeable;
/**
* This class provides global access to the centralized AppSearch index maintained by the system.
* Provides a connection to all AppSearch databases the querying application has been granted access
* to.
*
* <p>Apps can retrieve indexed documents through the {@link #search} API.
* <p>All implementations of this interface must be thread safe.
*
* @see AppSearchSessionShim
*/
public interface GlobalSearchSessionShim extends Closeable {
/**

View File

@@ -91,7 +91,7 @@ public class AppSearchPerson extends GenericDocument {
String uri;
try {
uri = UriCodec.decode(
getUri(), false /* convertPlus */, StandardCharsets.UTF_8,
getId(), false /* convertPlus */, StandardCharsets.UTF_8,
true /* throwOnFailure */);
} catch (IllegalArgumentException e) {
uri = null;

View File

@@ -153,8 +153,8 @@ public class AppSearchShortcutInfo extends GenericDocument {
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
.build()
).addProperty(new AppSearchSchema.DocumentPropertyConfig.Builder(KEY_PERSON)
.setSchemaType(AppSearchPerson.SCHEMA_TYPE)
).addProperty(new AppSearchSchema.DocumentPropertyConfig.Builder(
KEY_PERSON, AppSearchPerson.SCHEMA_TYPE)
.setCardinality(AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
.build()
@@ -419,7 +419,7 @@ public class AppSearchShortcutInfo extends GenericDocument {
final String bitmapPath = getPropertyString(KEY_BITMAP_PATH);
final int disabledReason = Integer.parseInt(getPropertyString(KEY_DISABLED_REASON));
final ShortcutInfo si = new ShortcutInfo(
userId, getUri(), packageName, activity, icon, shortLabel, shortLabelResId,
userId, getId(), packageName, activity, icon, shortLabel, shortLabelResId,
shortLabelResName, longLabel, longLabelResId, longLabelResName, disabledMessage,
disabledMessageResId, disabledMessageResName, categoriesSet, intents, rank, extras,
getCreationTimestampMillis(), flags, iconResId, iconResName, bitmapPath, iconUri,

View File

@@ -25,7 +25,7 @@ public class AppSearchEmailTest {
@Test
public void testBuildEmailAndGetValue() {
AppSearchEmail email =
new AppSearchEmail.Builder("namespace", "uri")
new AppSearchEmail.Builder("namespace", "id")
.setFrom("FakeFromAddress")
.setCc("CC1", "CC2")
// Score and Property are mixed into the middle to make sure
@@ -38,7 +38,7 @@ public class AppSearchEmailTest {
.build();
assertThat(email.getNamespace()).isEqualTo("namespace");
assertThat(email.getUri()).isEqualTo("uri");
assertThat(email.getId()).isEqualTo("id");
assertThat(email.getFrom()).isEqualTo("FakeFromAddress");
assertThat(email.getTo()).isNull();
assertThat(email.getCc()).asList().containsExactly("CC1", "CC2");

View File

@@ -27,13 +27,13 @@ public class GenericDocumentTest {
@Test
public void testRecreateFromParcel() {
GenericDocument inDoc =
new GenericDocument.Builder<>("namespace", "uri1", "schema1")
new GenericDocument.Builder<>("namespace", "id1", "schema1")
.setScore(42)
.setPropertyString("propString", "Hello")
.setPropertyBytes("propBytes", new byte[][] {{1, 2}})
.setPropertyDocument(
"propDocument",
new GenericDocument.Builder<>("namespace", "uri2", "schema2")
new GenericDocument.Builder<>("namespace", "id2", "schema2")
.setPropertyString("propString", "Goodbye")
.setPropertyBytes("propBytes", new byte[][] {{3, 4}})
.build())

View File

@@ -36,7 +36,7 @@ public class PutDocumentsRequestTest {
PutDocumentsRequest request =
new PutDocumentsRequest.Builder().addGenericDocuments(emails).build();
assertThat(request.getGenericDocuments().get(0).getUri()).isEqualTo("test1");
assertThat(request.getGenericDocuments().get(1).getUri()).isEqualTo("test2");
assertThat(request.getGenericDocuments().get(0).getId()).isEqualTo("test1");
assertThat(request.getGenericDocuments().get(1).getId()).isEqualTo("test2");
}
}

View File

@@ -23,10 +23,10 @@ import android.app.appsearch.AppSearchManager;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSession;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.GetByUriRequest;
import android.app.appsearch.GetByDocumentIdRequest;
import android.app.appsearch.PackageIdentifier;
import android.app.appsearch.PutDocumentsRequest;
import android.app.appsearch.RemoveByUriRequest;
import android.app.appsearch.RemoveByDocumentIdRequest;
import android.app.appsearch.ReportUsageRequest;
import android.app.appsearch.SearchResult;
import android.app.appsearch.SearchResults;
@@ -449,8 +449,8 @@ class ShortcutPackage extends ShortcutPackageItem {
session -> {
final AndroidFuture<Boolean> future = new AndroidFuture<>();
session.reportUsage(
new ReportUsageRequest.Builder(getPackageName())
.setUri(newShortcut.getId()).build(),
new ReportUsageRequest.Builder(
getPackageName(), newShortcut.getId()).build(),
mShortcutUser.mExecutor,
result -> future.complete(result.isSuccess()));
return future;
@@ -2377,7 +2377,8 @@ class ShortcutPackage extends ShortcutPackageItem {
}
awaitInAppSearch("Removing shortcut with id=" + id, session -> {
final AndroidFuture<Boolean> future = new AndroidFuture<>();
session.remove(new RemoveByUriRequest.Builder(getPackageName()).addUris(id).build(),
session.remove(
new RemoveByDocumentIdRequest.Builder(getPackageName()).addIds(id).build(),
mShortcutUser.mExecutor, result -> {
if (!result.isSuccess()) {
final Map<String, AppSearchResult<Void>> failures =
@@ -2420,8 +2421,9 @@ class ShortcutPackage extends ShortcutPackageItem {
}
return awaitInAppSearch("Getting shortcut by id", session -> {
final AndroidFuture<List<ShortcutInfo>> future = new AndroidFuture<>();
session.getByUri(
new GetByUriRequest.Builder(getPackageName()).addUris(shortcutIds).build(),
session.getByDocumentId(
new GetByDocumentIdRequest.Builder(getPackageName())
.addIds(shortcutIds).build(),
mShortcutUser.mExecutor,
results -> {
final List<ShortcutInfo> ret = new ArrayList<>(1);

View File

@@ -307,13 +307,13 @@ public class AppSearchImplTest {
public void testAddDocumentTypePrefix() {
DocumentProto insideDocument =
DocumentProto.newBuilder()
.setUri("inside-uri")
.setUri("inside-id")
.setSchema("type")
.setNamespace("namespace")
.build();
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri("uri")
.setUri("id")
.setSchema("type")
.setNamespace("namespace")
.addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument))
@@ -321,13 +321,13 @@ public class AppSearchImplTest {
DocumentProto expectedInsideDocument =
DocumentProto.newBuilder()
.setUri("inside-uri")
.setUri("inside-id")
.setSchema("package$databaseName/type")
.setNamespace("package$databaseName/namespace")
.build();
DocumentProto expectedDocumentProto =
DocumentProto.newBuilder()
.setUri("uri")
.setUri("id")
.setSchema("package$databaseName/type")
.setNamespace("package$databaseName/namespace")
.addProperties(
@@ -344,13 +344,13 @@ public class AppSearchImplTest {
public void testRemoveDocumentTypePrefixes() throws Exception {
DocumentProto insideDocument =
DocumentProto.newBuilder()
.setUri("inside-uri")
.setUri("inside-id")
.setSchema("package$databaseName/type")
.setNamespace("package$databaseName/namespace")
.build();
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri("uri")
.setUri("id")
.setSchema("package$databaseName/type")
.setNamespace("package$databaseName/namespace")
.addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument))
@@ -358,14 +358,14 @@ public class AppSearchImplTest {
DocumentProto expectedInsideDocument =
DocumentProto.newBuilder()
.setUri("inside-uri")
.setUri("inside-id")
.setSchema("type")
.setNamespace("namespace")
.build();
DocumentProto expectedDocumentProto =
DocumentProto.newBuilder()
.setUri("uri")
.setUri("id")
.setSchema("type")
.setNamespace("namespace")
.addProperties(
@@ -383,7 +383,7 @@ public class AppSearchImplTest {
// Set two different database names in the document, which should never happen
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri("uri")
.setUri("id")
.setSchema("prefix1/type")
.setNamespace("prefix2/namespace")
.build();
@@ -401,13 +401,13 @@ public class AppSearchImplTest {
// happen.
DocumentProto insideDocument =
DocumentProto.newBuilder()
.setUri("inside-uri")
.setUri("inside-id")
.setSchema("prefix1/type")
.setNamespace("prefix1/namespace")
.build();
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri("uri")
.setUri("id")
.setSchema("prefix2/type")
.setNamespace("prefix2/namespace")
.addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument))
@@ -441,7 +441,7 @@ public class AppSearchImplTest {
+ AppSearchImpl.CHECK_OPTIMIZE_INTERVAL;
i++) {
GenericDocument document =
new GenericDocument.Builder<>("namespace", "uri" + i, "type").build();
new GenericDocument.Builder<>("namespace", "id" + i, "type").build();
mAppSearchImpl.putDocument("package", "database", document, /*logger=*/ null);
}
@@ -452,7 +452,7 @@ public class AppSearchImplTest {
// delete 999 documents, we will reach the threshold to trigger optimize() in next
// deletion.
for (int i = 0; i < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT - 1; i++) {
mAppSearchImpl.remove("package", "database", "namespace", "uri" + i);
mAppSearchImpl.remove("package", "database", "namespace", "id" + i);
}
// Updates the check for optimize counter, checkForOptimize() will be triggered since
@@ -472,7 +472,7 @@ public class AppSearchImplTest {
< AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT
+ AppSearchImpl.CHECK_OPTIMIZE_INTERVAL;
i++) {
mAppSearchImpl.remove("package", "database", "namespace", "uri" + i);
mAppSearchImpl.remove("package", "database", "namespace", "id" + i);
}
// updates the check for optimize counter, will reach both CHECK_OPTIMIZE_INTERVAL and
// OPTIMIZE_THRESHOLD_DOC_COUNT this time and trigger a optimize().
@@ -501,8 +501,7 @@ public class AppSearchImplTest {
/*version=*/ 0);
// Insert document
GenericDocument document =
new GenericDocument.Builder<>("namespace", "uri", "type").build();
GenericDocument document = new GenericDocument.Builder<>("namespace", "id", "type").build();
mAppSearchImpl.putDocument("package", "database", document, /*logger=*/ null);
// Rewrite SearchSpec
@@ -544,11 +543,11 @@ public class AppSearchImplTest {
// Insert documents
GenericDocument document1 =
new GenericDocument.Builder<>("namespace", "uri", "typeA").build();
new GenericDocument.Builder<>("namespace", "id", "typeA").build();
mAppSearchImpl.putDocument("package", "database1", document1, /*logger=*/ null);
GenericDocument document2 =
new GenericDocument.Builder<>("namespace", "uri", "typeB").build();
new GenericDocument.Builder<>("namespace", "id", "typeB").build();
mAppSearchImpl.putDocument("package", "database2", document2, /*logger=*/ null);
// Rewrite SearchSpec
@@ -587,8 +586,7 @@ public class AppSearchImplTest {
/*version=*/ 0);
// Insert document
GenericDocument document =
new GenericDocument.Builder<>("namespace", "uri", "type").build();
GenericDocument document = new GenericDocument.Builder<>("namespace", "id", "type").build();
mAppSearchImpl.putDocument("package", "database", document, /*logger=*/ null);
// If 'allowedPrefixedSchemas' is empty, this returns false since there's nothing to
@@ -642,7 +640,7 @@ public class AppSearchImplTest {
// Insert package1 document
GenericDocument document =
new GenericDocument.Builder<>("namespace", "uri", "schema1").build();
new GenericDocument.Builder<>("namespace", "id", "schema1").build();
mAppSearchImpl.putDocument("package1", "database1", document, /*logger=*/ null);
// No query filters specified, package2 shouldn't be able to query for package1's documents.
@@ -653,7 +651,7 @@ public class AppSearchImplTest {
assertThat(searchResultPage.getResults()).isEmpty();
// Insert package2 document
document = new GenericDocument.Builder<>("namespace", "uri", "schema2").build();
document = new GenericDocument.Builder<>("namespace", "id", "schema2").build();
mAppSearchImpl.putDocument("package2", "database2", document, /*logger=*/ null);
// No query filters specified. package2 should only get its own documents back.
@@ -694,7 +692,7 @@ public class AppSearchImplTest {
// Insert package1 document
GenericDocument document =
new GenericDocument.Builder<>("namespace", "uri", "schema1").build();
new GenericDocument.Builder<>("namespace", "id", "schema1").build();
mAppSearchImpl.putDocument("package1", "database1", document, /*logger=*/ null);
// "package1" filter specified, but package2 shouldn't be able to query for package1's
@@ -709,7 +707,7 @@ public class AppSearchImplTest {
assertThat(searchResultPage.getResults()).isEmpty();
// Insert package2 document
document = new GenericDocument.Builder<>("namespace", "uri", "schema2").build();
document = new GenericDocument.Builder<>("namespace", "id", "schema2").build();
mAppSearchImpl.putDocument("package2", "database2", document, /*logger=*/ null);
// "package2" filter specified, package2 should only get its own documents back.
@@ -1028,7 +1026,7 @@ public class AppSearchImplTest {
// Insert package document
GenericDocument document =
new GenericDocument.Builder<>("namespace", "uri", "schema").build();
new GenericDocument.Builder<>("namespace", "id", "schema").build();
mAppSearchImpl.putDocument("package", "database", document, /*logger=*/ null);
// Verify the document is indexed.
@@ -1135,14 +1133,14 @@ public class AppSearchImplTest {
+ PrefixUtil.PACKAGE_DELIMITER
+ "databaseName"
+ PrefixUtil.DATABASE_DELIMITER;
final String uri = "uri";
final String id = "id";
final String namespace = prefix + "namespace";
final String schemaType = prefix + "schema";
// Building the SearchResult received from query.
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri(uri)
.setUri(id)
.setNamespace(namespace)
.setSchema(schemaType)
.build();
@@ -1185,32 +1183,32 @@ public class AppSearchImplTest {
// Insert two docs
GenericDocument document1 =
new GenericDocument.Builder<>("namespace", "uri1", "type").build();
new GenericDocument.Builder<>("namespace", "id1", "type").build();
GenericDocument document2 =
new GenericDocument.Builder<>("namespace", "uri2", "type").build();
new GenericDocument.Builder<>("namespace", "id2", "type").build();
mAppSearchImpl.putDocument("package", "database", document1, /*logger=*/ null);
mAppSearchImpl.putDocument("package", "database", document2, /*logger=*/ null);
// Report some usages. uri1 has 2 app and 1 system usage, uri2 has 1 app and 2 system usage.
// Report some usages. id1 has 2 app and 1 system usage, id2 has 1 app and 2 system usage.
mAppSearchImpl.reportUsage(
"package",
"database",
"namespace",
"uri1",
"id1",
/*usageTimestampMillis=*/ 10,
/*systemUsage=*/ false);
mAppSearchImpl.reportUsage(
"package",
"database",
"namespace",
"uri1",
"id1",
/*usageTimestampMillis=*/ 20,
/*systemUsage=*/ false);
mAppSearchImpl.reportUsage(
"package",
"database",
"namespace",
"uri1",
"id1",
/*usageTimestampMillis=*/ 1000,
/*systemUsage=*/ true);
@@ -1218,25 +1216,25 @@ public class AppSearchImplTest {
"package",
"database",
"namespace",
"uri2",
"id2",
/*usageTimestampMillis=*/ 100,
/*systemUsage=*/ false);
mAppSearchImpl.reportUsage(
"package",
"database",
"namespace",
"uri2",
"id2",
/*usageTimestampMillis=*/ 200,
/*systemUsage=*/ true);
mAppSearchImpl.reportUsage(
"package",
"database",
"namespace",
"uri2",
"id2",
/*usageTimestampMillis=*/ 150,
/*systemUsage=*/ true);
// Sort by app usage count: uri1 should win
// Sort by app usage count: id1 should win
List<SearchResult> page =
mAppSearchImpl
.query(
@@ -1249,10 +1247,10 @@ public class AppSearchImplTest {
.build())
.getResults();
assertThat(page).hasSize(2);
assertThat(page.get(0).getGenericDocument().getUri()).isEqualTo("uri1");
assertThat(page.get(1).getGenericDocument().getUri()).isEqualTo("uri2");
assertThat(page.get(0).getGenericDocument().getId()).isEqualTo("id1");
assertThat(page.get(1).getGenericDocument().getId()).isEqualTo("id2");
// Sort by app usage timestamp: uri2 should win
// Sort by app usage timestamp: id2 should win
page =
mAppSearchImpl
.query(
@@ -1267,10 +1265,10 @@ public class AppSearchImplTest {
.build())
.getResults();
assertThat(page).hasSize(2);
assertThat(page.get(0).getGenericDocument().getUri()).isEqualTo("uri2");
assertThat(page.get(1).getGenericDocument().getUri()).isEqualTo("uri1");
assertThat(page.get(0).getGenericDocument().getId()).isEqualTo("id2");
assertThat(page.get(1).getGenericDocument().getId()).isEqualTo("id1");
// Sort by system usage count: uri2 should win
// Sort by system usage count: id2 should win
page =
mAppSearchImpl
.query(
@@ -1284,10 +1282,10 @@ public class AppSearchImplTest {
.build())
.getResults();
assertThat(page).hasSize(2);
assertThat(page.get(0).getGenericDocument().getUri()).isEqualTo("uri2");
assertThat(page.get(1).getGenericDocument().getUri()).isEqualTo("uri1");
assertThat(page.get(0).getGenericDocument().getId()).isEqualTo("id2");
assertThat(page.get(1).getGenericDocument().getId()).isEqualTo("id1");
// Sort by system usage timestamp: uri1 should win
// Sort by system usage timestamp: id1 should win
page =
mAppSearchImpl
.query(
@@ -1302,8 +1300,8 @@ public class AppSearchImplTest {
.build())
.getResults();
assertThat(page).hasSize(2);
assertThat(page.get(0).getGenericDocument().getUri()).isEqualTo("uri1");
assertThat(page.get(1).getGenericDocument().getUri()).isEqualTo("uri2");
assertThat(page.get(0).getGenericDocument().getId()).isEqualTo("id1");
assertThat(page.get(1).getGenericDocument().getId()).isEqualTo("id2");
}
@Test
@@ -1353,7 +1351,7 @@ public class AppSearchImplTest {
// Insert document for "package1"
GenericDocument document =
new GenericDocument.Builder<>("namespace", "uri1", "type").build();
new GenericDocument.Builder<>("namespace", "id1", "type").build();
mAppSearchImpl.putDocument("package1", "database", document, /*logger=*/ null);
// Insert schema for "package2"
@@ -1367,9 +1365,9 @@ public class AppSearchImplTest {
/*version=*/ 0);
// Insert two documents for "package2"
document = new GenericDocument.Builder<>("namespace", "uri1", "type").build();
document = new GenericDocument.Builder<>("namespace", "id1", "type").build();
mAppSearchImpl.putDocument("package2", "database", document, /*logger=*/ null);
document = new GenericDocument.Builder<>("namespace", "uri2", "type").build();
document = new GenericDocument.Builder<>("namespace", "id2", "type").build();
mAppSearchImpl.putDocument("package2", "database", document, /*logger=*/ null);
StorageInfo storageInfo = mAppSearchImpl.getStorageInfoForPackage("package1");
@@ -1467,13 +1465,13 @@ public class AppSearchImplTest {
// Add a document for "package1", "database1"
GenericDocument document =
new GenericDocument.Builder<>("namespace1", "uri1", "type").build();
new GenericDocument.Builder<>("namespace1", "id1", "type").build();
mAppSearchImpl.putDocument("package1", "database1", document, /*logger=*/ null);
// Add two documents for "package1", "database2"
document = new GenericDocument.Builder<>("namespace1", "uri1", "type").build();
document = new GenericDocument.Builder<>("namespace1", "id1", "type").build();
mAppSearchImpl.putDocument("package1", "database2", document, /*logger=*/ null);
document = new GenericDocument.Builder<>("namespace1", "uri2", "type").build();
document = new GenericDocument.Builder<>("namespace1", "id2", "type").build();
mAppSearchImpl.putDocument("package1", "database2", document, /*logger=*/ null);
StorageInfo storageInfo = mAppSearchImpl.getStorageInfoForDatabase("package1", "database1");
@@ -1543,7 +1541,7 @@ public class AppSearchImplTest {
appSearchImpl.putDocument(
"package",
"database",
new GenericDocument.Builder<>("namespace", "uri", "type").build(),
new GenericDocument.Builder<>("namespace", "id", "type").build(),
/*logger=*/ null);
});
@@ -1551,7 +1549,7 @@ public class AppSearchImplTest {
IllegalStateException.class,
() -> {
appSearchImpl.getDocument(
"package", "database", "namespace", "uri", Collections.emptyMap());
"package", "database", "namespace", "id", Collections.emptyMap());
});
expectThrows(
@@ -1597,7 +1595,7 @@ public class AppSearchImplTest {
"package",
"database",
"namespace",
"uri",
"id",
/*usageTimestampMillis=*/ 1000L,
/*systemUsage=*/ false);
});
@@ -1605,7 +1603,7 @@ public class AppSearchImplTest {
expectThrows(
IllegalStateException.class,
() -> {
appSearchImpl.remove("package", "database", "namespace", "uri");
appSearchImpl.remove("package", "database", "namespace", "id");
});
expectThrows(
@@ -1664,13 +1662,13 @@ public class AppSearchImplTest {
// Add a document and persist it.
GenericDocument document =
new GenericDocument.Builder<>("namespace1", "uri1", "type").build();
new GenericDocument.Builder<>("namespace1", "id1", "type").build();
appSearchImpl.putDocument("package", "database", document, /*logger=*/ null);
appSearchImpl.persistToDisk(PersistType.Code.LITE);
GenericDocument getResult =
appSearchImpl.getDocument(
"package", "database", "namespace1", "uri1", Collections.emptyMap());
"package", "database", "namespace1", "id1", Collections.emptyMap());
assertThat(getResult).isEqualTo(document);
// That document should be visible even from another instance.
@@ -1682,7 +1680,7 @@ public class AppSearchImplTest {
/*globalQuerierPackage=*/ "");
getResult =
appSearchImpl2.getDocument(
"package", "database", "namespace1", "uri1", Collections.emptyMap());
"package", "database", "namespace1", "id1", Collections.emptyMap());
assertThat(getResult).isEqualTo(document);
}
@@ -1711,24 +1709,24 @@ public class AppSearchImplTest {
// Add two documents and persist them.
GenericDocument document1 =
new GenericDocument.Builder<>("namespace1", "uri1", "type").build();
new GenericDocument.Builder<>("namespace1", "id1", "type").build();
appSearchImpl.putDocument("package", "database", document1, /*logger=*/ null);
GenericDocument document2 =
new GenericDocument.Builder<>("namespace1", "uri2", "type").build();
new GenericDocument.Builder<>("namespace1", "id2", "type").build();
appSearchImpl.putDocument("package", "database", document2, /*logger=*/ null);
appSearchImpl.persistToDisk(PersistType.Code.LITE);
GenericDocument getResult =
appSearchImpl.getDocument(
"package", "database", "namespace1", "uri1", Collections.emptyMap());
"package", "database", "namespace1", "id1", Collections.emptyMap());
assertThat(getResult).isEqualTo(document1);
getResult =
appSearchImpl.getDocument(
"package", "database", "namespace1", "uri2", Collections.emptyMap());
"package", "database", "namespace1", "id2", Collections.emptyMap());
assertThat(getResult).isEqualTo(document2);
// Delete the first document
appSearchImpl.remove("package", "database", "namespace1", "uri1");
appSearchImpl.remove("package", "database", "namespace1", "id1");
appSearchImpl.persistToDisk(PersistType.Code.LITE);
expectThrows(
AppSearchException.class,
@@ -1737,11 +1735,11 @@ public class AppSearchImplTest {
"package",
"database",
"namespace1",
"uri1",
"id1",
Collections.emptyMap()));
getResult =
appSearchImpl.getDocument(
"package", "database", "namespace1", "uri2", Collections.emptyMap());
"package", "database", "namespace1", "id2", Collections.emptyMap());
assertThat(getResult).isEqualTo(document2);
// Only the second document should be retrievable from another instance.
@@ -1758,11 +1756,11 @@ public class AppSearchImplTest {
"package",
"database",
"namespace1",
"uri1",
"id1",
Collections.emptyMap()));
getResult =
appSearchImpl2.getDocument(
"package", "database", "namespace1", "uri2", Collections.emptyMap());
"package", "database", "namespace1", "id2", Collections.emptyMap());
assertThat(getResult).isEqualTo(document2);
}
@@ -1791,20 +1789,20 @@ public class AppSearchImplTest {
// Add two documents and persist them.
GenericDocument document1 =
new GenericDocument.Builder<>("namespace1", "uri1", "type").build();
new GenericDocument.Builder<>("namespace1", "id1", "type").build();
appSearchImpl.putDocument("package", "database", document1, /*logger=*/ null);
GenericDocument document2 =
new GenericDocument.Builder<>("namespace2", "uri2", "type").build();
new GenericDocument.Builder<>("namespace2", "id2", "type").build();
appSearchImpl.putDocument("package", "database", document2, /*logger=*/ null);
appSearchImpl.persistToDisk(PersistType.Code.LITE);
GenericDocument getResult =
appSearchImpl.getDocument(
"package", "database", "namespace1", "uri1", Collections.emptyMap());
"package", "database", "namespace1", "id1", Collections.emptyMap());
assertThat(getResult).isEqualTo(document1);
getResult =
appSearchImpl.getDocument(
"package", "database", "namespace2", "uri2", Collections.emptyMap());
"package", "database", "namespace2", "id2", Collections.emptyMap());
assertThat(getResult).isEqualTo(document2);
// Delete the first document
@@ -1824,11 +1822,11 @@ public class AppSearchImplTest {
"package",
"database",
"namespace1",
"uri1",
"id1",
Collections.emptyMap()));
getResult =
appSearchImpl.getDocument(
"package", "database", "namespace2", "uri2", Collections.emptyMap());
"package", "database", "namespace2", "id2", Collections.emptyMap());
assertThat(getResult).isEqualTo(document2);
// Only the second document should be retrievable from another instance.
@@ -1845,11 +1843,11 @@ public class AppSearchImplTest {
"package",
"database",
"namespace1",
"uri1",
"id1",
Collections.emptyMap()));
getResult =
appSearchImpl2.getDocument(
"package", "database", "namespace2", "uri2", Collections.emptyMap());
"package", "database", "namespace2", "id2", Collections.emptyMap());
assertThat(getResult).isEqualTo(document2);
}
}

View File

@@ -129,8 +129,7 @@ public class AppSearchLoggerTest {
/*schemasPackageAccessible=*/ Collections.emptyMap(),
/*forceOverride=*/ false,
/*version=*/ 0);
GenericDocument document =
new GenericDocument.Builder<>("namespace", "uri", "type").build();
GenericDocument document = new GenericDocument.Builder<>("namespace", "id", "type").build();
mAppSearchImpl.putDocument(testPackageName, testDatabase, document, mLogger);

View File

@@ -64,7 +64,7 @@ public class GenericDocumentToProtoConverterTest {
public void testDocumentProtoConvert() {
GenericDocument document =
new GenericDocument.Builder<GenericDocument.Builder<?>>(
"namespace", "uri1", SCHEMA_TYPE_1)
"namespace", "id1", SCHEMA_TYPE_1)
.setCreationTimestampMillis(5L)
.setScore(1)
.setTtlMillis(1L)
@@ -80,7 +80,7 @@ public class GenericDocumentToProtoConverterTest {
// Create the Document proto. Need to sort the property order by key.
DocumentProto.Builder documentProtoBuilder =
DocumentProto.newBuilder()
.setUri("uri1")
.setUri("id1")
.setSchema(SCHEMA_TYPE_1)
.setCreationTimestampMs(5L)
.setScore(1)
@@ -140,7 +140,7 @@ public class GenericDocumentToProtoConverterTest {
String emptyStringPropertyName = "emptyStringProperty";
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri("uri1")
.setUri("id1")
.setSchema(SCHEMA_TYPE_1)
.setCreationTimestampMs(5L)
.setNamespace("namespace")
@@ -167,7 +167,7 @@ public class GenericDocumentToProtoConverterTest {
GenericDocument expectedDocument =
new GenericDocument.Builder<GenericDocument.Builder<?>>(
"namespace", "uri1", SCHEMA_TYPE_1)
"namespace", "id1", SCHEMA_TYPE_1)
.setCreationTimestampMillis(5L)
.setPropertyString(emptyStringPropertyName)
.build();
@@ -181,7 +181,7 @@ public class GenericDocumentToProtoConverterTest {
String documentPropertyName = "documentProperty";
DocumentProto nestedDocumentProto =
DocumentProto.newBuilder()
.setUri("uri2")
.setUri("id2")
.setSchema(SCHEMA_TYPE_2)
.setCreationTimestampMs(5L)
.setNamespace("namespace")
@@ -190,7 +190,7 @@ public class GenericDocumentToProtoConverterTest {
.build();
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri("uri1")
.setUri("id1")
.setSchema(SCHEMA_TYPE_1)
.setCreationTimestampMs(5L)
.setNamespace("namespace")
@@ -236,12 +236,12 @@ public class GenericDocumentToProtoConverterTest {
GenericDocument expectedDocument =
new GenericDocument.Builder<GenericDocument.Builder<?>>(
"namespace", "uri1", SCHEMA_TYPE_1)
"namespace", "id1", SCHEMA_TYPE_1)
.setCreationTimestampMillis(5L)
.setPropertyDocument(
documentPropertyName,
new GenericDocument.Builder<GenericDocument.Builder<?>>(
"namespace", "uri2", SCHEMA_TYPE_2)
"namespace", "id2", SCHEMA_TYPE_2)
.setCreationTimestampMillis(5L)
.setPropertyString(emptyStringPropertyName)
.build())

View File

@@ -54,22 +54,19 @@ public class SnippetTest {
"A commonly used fake word is foo.\n"
+ " Another nonsense word that’s used a lot\n"
+ " is bar.\n";
final String uri = "uri1";
final String searchWord = "foo";
final String id = "id1";
final String exactMatch = "foo";
final String window = "is foo";
// Building the SearchResult received from query.
PropertyProto property =
PropertyProto.newBuilder()
.setName(propertyKeyString)
.addStringValues(propertyValueString)
.build();
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri(uri)
.setUri(id)
.setSchema(SCHEMA_TYPE)
.addProperties(property)
.addProperties(
PropertyProto.newBuilder()
.setName(propertyKeyString)
.addStringValues(propertyValueString))
.build();
SnippetProto snippetProto =
SnippetProto.newBuilder()
@@ -81,17 +78,15 @@ public class SnippetTest {
.setExactMatchPosition(29)
.setExactMatchBytes(3)
.setWindowPosition(26)
.setWindowBytes(6)
.build())
.build())
.build();
SearchResultProto.ResultProto resultProto =
SearchResultProto.ResultProto.newBuilder()
.setDocument(documentProto)
.setSnippet(snippetProto)
.setWindowBytes(6)))
.build();
SearchResultProto searchResultProto =
SearchResultProto.newBuilder().addResults(resultProto).build();
SearchResultProto.newBuilder()
.addResults(
SearchResultProto.ResultProto.newBuilder()
.setDocument(documentProto)
.setSnippet(snippetProto))
.build();
// Making ResultReader and getting Snippet values.
SearchResultPage searchResultPage =
@@ -100,50 +95,45 @@ public class SnippetTest {
Collections.singletonList(PACKAGE_NAME),
Collections.singletonList(DATABASE_NAME),
SCHEMA_MAP);
for (SearchResult result : searchResultPage.getResults()) {
SearchResult.MatchInfo match = result.getMatches().get(0);
assertThat(match.getPropertyPath()).isEqualTo(propertyKeyString);
assertThat(match.getFullText()).isEqualTo(propertyValueString);
assertThat(match.getExactMatch()).isEqualTo(exactMatch);
assertThat(match.getExactMatchRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 29, /*upper=*/ 32));
assertThat(match.getFullText()).isEqualTo(propertyValueString);
assertThat(match.getSnippetRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 26, /*upper=*/ 32));
assertThat(match.getSnippet()).isEqualTo(window);
}
assertThat(searchResultPage.getResults()).hasSize(1);
SearchResult.MatchInfo match = searchResultPage.getResults().get(0).getMatches().get(0);
assertThat(match.getPropertyPath()).isEqualTo(propertyKeyString);
assertThat(match.getFullText()).isEqualTo(propertyValueString);
assertThat(match.getExactMatch()).isEqualTo(exactMatch);
assertThat(match.getExactMatchRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 29, /*upper=*/ 32));
assertThat(match.getFullText()).isEqualTo(propertyValueString);
assertThat(match.getSnippetRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 26, /*upper=*/ 32));
assertThat(match.getSnippet()).isEqualTo(window);
}
// TODO(tytytyww): Add tests for Double and Long Snippets.
@Test
public void testNoSnippets() throws Exception {
public void testNoSnippets() {
final String propertyKeyString = "content";
final String propertyValueString =
"A commonly used fake word is foo.\n"
+ " Another nonsense word that’s used a lot\n"
+ " is bar.\n";
final String uri = "uri1";
final String searchWord = "foo";
final String exactMatch = "foo";
final String window = "is foo";
final String id = "id1";
// Building the SearchResult received from query.
PropertyProto property =
PropertyProto.newBuilder()
.setName(propertyKeyString)
.addStringValues(propertyValueString)
.build();
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri(uri)
.setUri(id)
.setSchema(SCHEMA_TYPE)
.addProperties(property)
.addProperties(
PropertyProto.newBuilder()
.setName(propertyKeyString)
.addStringValues(propertyValueString))
.build();
SearchResultProto.ResultProto resultProto =
SearchResultProto.ResultProto.newBuilder().setDocument(documentProto).build();
SearchResultProto searchResultProto =
SearchResultProto.newBuilder().addResults(resultProto).build();
SearchResultProto.newBuilder()
.addResults(
SearchResultProto.ResultProto.newBuilder()
.setDocument(documentProto))
.build();
SearchResultPage searchResultPage =
SearchResultToProtoConverter.toSearchResultPage(
@@ -151,32 +141,108 @@ public class SnippetTest {
Collections.singletonList(PACKAGE_NAME),
Collections.singletonList(DATABASE_NAME),
SCHEMA_MAP);
for (SearchResult result : searchResultPage.getResults()) {
assertThat(result.getMatches()).isEmpty();
}
assertThat(searchResultPage.getResults()).hasSize(1);
assertThat(searchResultPage.getResults().get(0).getMatches()).isEmpty();
}
@Test
public void testMultipleStringSnippet() throws Exception {
final String searchWord = "Test";
public void testMultipleStringSnippet() {
// Building the SearchResult received from query.
PropertyProto property1 =
PropertyProto.newBuilder()
.setName("sender.name")
.addStringValues("Test Name Jr.")
.build();
PropertyProto property2 =
PropertyProto.newBuilder()
.setName("sender.email")
.addStringValues("TestNameJr@gmail.com")
.build();
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri("uri1")
.setSchema(SCHEMA_TYPE)
.addProperties(property1)
.addProperties(property2)
.addProperties(
PropertyProto.newBuilder()
.setName("senderName")
.addStringValues("Test Name Jr."))
.addProperties(
PropertyProto.newBuilder()
.setName("senderEmail")
.addStringValues("TestNameJr@gmail.com"))
.build();
SnippetProto snippetProto =
SnippetProto.newBuilder()
.addEntries(
SnippetProto.EntryProto.newBuilder()
.setPropertyName("senderName")
.addSnippetMatches(
SnippetMatchProto.newBuilder()
.setExactMatchPosition(0)
.setExactMatchBytes(4)
.setWindowPosition(0)
.setWindowBytes(9)))
.addEntries(
SnippetProto.EntryProto.newBuilder()
.setPropertyName("senderEmail")
.addSnippetMatches(
SnippetMatchProto.newBuilder()
.setExactMatchPosition(0)
.setExactMatchBytes(20)
.setWindowPosition(0)
.setWindowBytes(20)))
.build();
SearchResultProto searchResultProto =
SearchResultProto.newBuilder()
.addResults(
SearchResultProto.ResultProto.newBuilder()
.setDocument(documentProto)
.setSnippet(snippetProto))
.build();
// Making ResultReader and getting Snippet values.
SearchResultPage searchResultPage =
SearchResultToProtoConverter.toSearchResultPage(
searchResultProto,
Collections.singletonList(PACKAGE_NAME),
Collections.singletonList(DATABASE_NAME),
SCHEMA_MAP);
assertThat(searchResultPage.getResults()).hasSize(1);
SearchResult.MatchInfo match1 = searchResultPage.getResults().get(0).getMatches().get(0);
assertThat(match1.getPropertyPath()).isEqualTo("senderName");
assertThat(match1.getFullText()).isEqualTo("Test Name Jr.");
assertThat(match1.getExactMatchRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 4));
assertThat(match1.getExactMatch()).isEqualTo("Test");
assertThat(match1.getSnippetRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 9));
assertThat(match1.getSnippet()).isEqualTo("Test Name");
SearchResult.MatchInfo match2 = searchResultPage.getResults().get(0).getMatches().get(1);
assertThat(match2.getPropertyPath()).isEqualTo("senderEmail");
assertThat(match2.getFullText()).isEqualTo("TestNameJr@gmail.com");
assertThat(match2.getExactMatchRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 20));
assertThat(match2.getExactMatch()).isEqualTo("TestNameJr@gmail.com");
assertThat(match2.getSnippetRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 20));
assertThat(match2.getSnippet()).isEqualTo("TestNameJr@gmail.com");
}
@Test
public void testNestedDocumentSnippet() {
// Building the SearchResult received from query.
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri("id1")
.setSchema(SCHEMA_TYPE)
.addProperties(
PropertyProto.newBuilder()
.setName("sender")
.addDocumentValues(
DocumentProto.newBuilder()
.addProperties(
PropertyProto.newBuilder()
.setName("name")
.addStringValues(
"Test Name Jr."))
.addProperties(
PropertyProto.newBuilder()
.setName("email")
.addStringValues(
"TestNameJr@gmail.com")
.addStringValues(
"TestNameJr2@gmail.com"))))
.build();
SnippetProto snippetProto =
SnippetProto.newBuilder()
@@ -188,28 +254,24 @@ public class SnippetTest {
.setExactMatchPosition(0)
.setExactMatchBytes(4)
.setWindowPosition(0)
.setWindowBytes(9)
.build())
.build())
.setWindowBytes(9)))
.addEntries(
SnippetProto.EntryProto.newBuilder()
.setPropertyName("sender.email")
.setPropertyName("sender.email[1]")
.addSnippetMatches(
SnippetMatchProto.newBuilder()
.setExactMatchPosition(0)
.setExactMatchBytes(20)
.setExactMatchBytes(21)
.setWindowPosition(0)
.setWindowBytes(20)
.build())
.build())
.build();
SearchResultProto.ResultProto resultProto =
SearchResultProto.ResultProto.newBuilder()
.setDocument(documentProto)
.setSnippet(snippetProto)
.setWindowBytes(21)))
.build();
SearchResultProto searchResultProto =
SearchResultProto.newBuilder().addResults(resultProto).build();
SearchResultProto.newBuilder()
.addResults(
SearchResultProto.ResultProto.newBuilder()
.setDocument(documentProto)
.setSnippet(snippetProto))
.build();
// Making ResultReader and getting Snippet values.
SearchResultPage searchResultPage =
@@ -218,27 +280,25 @@ public class SnippetTest {
Collections.singletonList(PACKAGE_NAME),
Collections.singletonList(DATABASE_NAME),
SCHEMA_MAP);
for (SearchResult result : searchResultPage.getResults()) {
assertThat(searchResultPage.getResults()).hasSize(1);
SearchResult.MatchInfo match1 = searchResultPage.getResults().get(0).getMatches().get(0);
assertThat(match1.getPropertyPath()).isEqualTo("sender.name");
assertThat(match1.getFullText()).isEqualTo("Test Name Jr.");
assertThat(match1.getExactMatchRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 4));
assertThat(match1.getExactMatch()).isEqualTo("Test");
assertThat(match1.getSnippetRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 9));
assertThat(match1.getSnippet()).isEqualTo("Test Name");
SearchResult.MatchInfo match1 = result.getMatches().get(0);
assertThat(match1.getPropertyPath()).isEqualTo("sender.name");
assertThat(match1.getFullText()).isEqualTo("Test Name Jr.");
assertThat(match1.getExactMatchRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 4));
assertThat(match1.getExactMatch()).isEqualTo("Test");
assertThat(match1.getSnippetRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 9));
assertThat(match1.getSnippet()).isEqualTo("Test Name");
SearchResult.MatchInfo match2 = result.getMatches().get(1);
assertThat(match2.getPropertyPath()).isEqualTo("sender.email");
assertThat(match2.getFullText()).isEqualTo("TestNameJr@gmail.com");
assertThat(match2.getExactMatchRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 20));
assertThat(match2.getExactMatch()).isEqualTo("TestNameJr@gmail.com");
assertThat(match2.getSnippetRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 20));
assertThat(match2.getSnippet()).isEqualTo("TestNameJr@gmail.com");
}
SearchResult.MatchInfo match2 = searchResultPage.getResults().get(0).getMatches().get(1);
assertThat(match2.getPropertyPath()).isEqualTo("sender.email[1]");
assertThat(match2.getFullText()).isEqualTo("TestNameJr2@gmail.com");
assertThat(match2.getExactMatchRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 21));
assertThat(match2.getExactMatch()).isEqualTo("TestNameJr2@gmail.com");
assertThat(match2.getSnippetRange())
.isEqualTo(new SearchResult.MatchRange(/*lower=*/ 0, /*upper=*/ 21));
assertThat(match2.getSnippet()).isEqualTo("TestNameJr2@gmail.com");
}
}

View File

@@ -704,36 +704,36 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
final String key = getKey(userId, databaseName);
Map<String, GenericDocument> docMap = mDocumentMap.get(key);
for (GenericDocument doc : docs) {
builder.setSuccess(doc.getUri(), null);
builder.setSuccess(doc.getId(), null);
if (docMap == null) {
docMap = new ArrayMap<>(1);
mDocumentMap.put(key, docMap);
}
docMap.put(doc.getUri(), doc);
docMap.put(doc.getId(), doc);
}
callback.onResult(builder.build());
}
@Override
public void getDocuments(String packageName, String databaseName, String namespace,
List<String> uris, Map<String, List<String>> typePropertyPaths, int userId,
List<String> ids, Map<String, List<String>> typePropertyPaths, int userId,
IAppSearchBatchResultCallback callback) throws RemoteException {
final AppSearchBatchResult.Builder<String, Bundle> builder =
new AppSearchBatchResult.Builder<>();
final String key = getKey(userId, databaseName);
if (!mDocumentMap.containsKey(key)) {
for (String uri : uris) {
builder.setFailure(uri, AppSearchResult.RESULT_NOT_FOUND,
key + " not found when getting: " + uri);
for (String id : ids) {
builder.setFailure(id, AppSearchResult.RESULT_NOT_FOUND,
key + " not found when getting: " + id);
}
} else {
final Map<String, GenericDocument> docs = mDocumentMap.get(key);
for (String uri : uris) {
if (docs.containsKey(uri)) {
builder.setSuccess(uri, docs.get(uri).getBundle());
for (String id : ids) {
if (docs.containsKey(id)) {
builder.setSuccess(id, docs.get(id).getBundle());
} else {
builder.setFailure(uri, AppSearchResult.RESULT_NOT_FOUND,
"shortcut not found: " + uri);
builder.setFailure(id, AppSearchResult.RESULT_NOT_FOUND,
"shortcut not found: " + id);
}
}
}
@@ -805,33 +805,33 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
@Override
public void reportUsage(String packageName, String databaseName, String namespace,
String uri, long usageTimeMillis, boolean systemUsage, int userId,
String documentId, long usageTimestampMillis, boolean systemUsage, int userId,
IAppSearchResultCallback callback)
throws RemoteException {
ignore(callback);
}
@Override
public void removeByUri(String packageName, String databaseName, String namespace,
List<String> uris, int userId, IAppSearchBatchResultCallback callback)
public void removeByDocumentId(String packageName, String databaseName, String namespace,
List<String> ids, int userId, IAppSearchBatchResultCallback callback)
throws RemoteException {
final AppSearchBatchResult.Builder<String, Void> builder =
new AppSearchBatchResult.Builder<>();
final String key = getKey(userId, databaseName);
if (!mDocumentMap.containsKey(key)) {
for (String uri : uris) {
builder.setFailure(uri, AppSearchResult.RESULT_NOT_FOUND,
"package " + key + " not found when removing " + uri);
for (String id : ids) {
builder.setFailure(id, AppSearchResult.RESULT_NOT_FOUND,
"package " + key + " not found when removing " + id);
}
} else {
final Map<String, GenericDocument> docs = mDocumentMap.get(key);
for (String uri : uris) {
if (docs.containsKey(uri)) {
docs.remove(uri);
builder.setSuccess(uri, null);
for (String id : ids) {
if (docs.containsKey(id)) {
docs.remove(id);
builder.setSuccess(id, null);
} else {
builder.setFailure(uri, AppSearchResult.RESULT_NOT_FOUND,
"shortcut not found when removing " + uri);
builder.setFailure(id, AppSearchResult.RESULT_NOT_FOUND,
"shortcut not found when removing " + id);
}
}
}