Pass package name across binder.
Take the client's context package name and pass it across binder so we can forward it to AppSearchImpl. We'll no longer be getting package name from UID, but we'll still verify that the package name belongs to the binder calling UID. Bug: 177752194 Test: presubmit Change-Id: I8aef10594a6130790e28fa34d87ab89717159d79
This commit is contained in:
@@ -46,6 +46,7 @@ import java.util.function.Consumer;
|
||||
public class AppSearchManager {
|
||||
/**
|
||||
* The default empty database name.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final String DEFAULT_DATABASE_NAME = "";
|
||||
@@ -70,8 +71,8 @@ public class AppSearchManager {
|
||||
/**
|
||||
* Returns the name of the database to create or open.
|
||||
*
|
||||
* <p>Databases with different names are fully separate with distinct types, namespaces,
|
||||
* and data.
|
||||
* <p>Databases with different names are fully separate with distinct types, namespaces, and
|
||||
* data.
|
||||
*/
|
||||
@NonNull
|
||||
public String getDatabaseName() {
|
||||
@@ -126,11 +127,11 @@ public class AppSearchManager {
|
||||
* initialization process will create one under the user's credential encrypted directory.
|
||||
*
|
||||
* @param searchContext The {@link SearchContext} contains all information to create a new
|
||||
* {@link AppSearchSession}
|
||||
* @param executor Executor on which to invoke the callback.
|
||||
* @param callback The {@link AppSearchResult}<{@link AppSearchSession}> of
|
||||
* performing this operation. Or a {@link AppSearchResult} with failure
|
||||
* reason code and error information.
|
||||
* {@link AppSearchSession}
|
||||
* @param executor Executor on which to invoke the callback.
|
||||
* @param callback The {@link AppSearchResult}<{@link AppSearchSession}> of performing
|
||||
* this operation. Or a {@link AppSearchResult} with failure reason code and error
|
||||
* information.
|
||||
*/
|
||||
public void createSearchSession(
|
||||
@NonNull SearchContext searchContext,
|
||||
@@ -140,7 +141,12 @@ public class AppSearchManager {
|
||||
Objects.requireNonNull(executor);
|
||||
Objects.requireNonNull(callback);
|
||||
AppSearchSession.createSearchSession(
|
||||
searchContext, mService, mContext.getUserId(), executor, callback);
|
||||
searchContext,
|
||||
mService,
|
||||
mContext.getUserId(),
|
||||
getPackageName(),
|
||||
executor,
|
||||
callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,10 +155,10 @@ public class AppSearchManager {
|
||||
* <p>This process requires an AppSearch native indexing file system. If it's not created, the
|
||||
* initialization process will create one under the user's credential encrypted directory.
|
||||
*
|
||||
* @param executor Executor on which to invoke the callback.
|
||||
* @param callback The {@link AppSearchResult}<{@link GlobalSearchSession}> of
|
||||
* performing this operation. Or a {@link AppSearchResult} with failure
|
||||
* reason code and error information.
|
||||
* @param executor Executor on which to invoke the callback.
|
||||
* @param callback The {@link AppSearchResult}<{@link GlobalSearchSession}> of performing
|
||||
* this operation. Or a {@link AppSearchResult} with failure reason code and error
|
||||
* information.
|
||||
*/
|
||||
public void createGlobalSearchSession(
|
||||
@NonNull @CallbackExecutor Executor executor,
|
||||
@@ -160,7 +166,7 @@ public class AppSearchManager {
|
||||
Objects.requireNonNull(executor);
|
||||
Objects.requireNonNull(callback);
|
||||
GlobalSearchSession.createGlobalSearchSession(
|
||||
mService, mContext.getUserId(), executor, callback);
|
||||
mService, mContext.getUserId(), getPackageName(), executor, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,40 +176,42 @@ public class AppSearchManager {
|
||||
* to {@link #setSchema}, if any, to determine how to treat existing documents. The following
|
||||
* types of schema modifications are always safe and are made without deleting any existing
|
||||
* documents:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Addition of new types
|
||||
* <li>Addition of new
|
||||
* {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL
|
||||
* OPTIONAL} or
|
||||
* {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED
|
||||
* REPEATED} properties to a type
|
||||
* <li>Changing the cardinality of a data type to be less restrictive (e.g. changing an
|
||||
* {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL
|
||||
* OPTIONAL} property into a
|
||||
* {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED
|
||||
* REPEATED} property.
|
||||
* <li>Addition of new types
|
||||
* <li>Addition of new {@link
|
||||
* android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL} or
|
||||
* {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED
|
||||
* REPEATED} properties to a type
|
||||
* <li>Changing the cardinality of a data type to be less restrictive (e.g. changing an {@link
|
||||
* android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL}
|
||||
* property into a {@link
|
||||
* android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REPEATED REPEATED}
|
||||
* property.
|
||||
* </ul>
|
||||
*
|
||||
* <p>The following types of schema changes are not backwards-compatible:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Removal of an existing type
|
||||
* <li>Removal of a property from a type
|
||||
* <li>Changing the data type ({@code boolean}, {@code long}, etc.) of an existing property
|
||||
* <li>For properties of {@code GenericDocument} type, changing the schema type of
|
||||
* {@code GenericDocument}s of that property
|
||||
* <li>Changing the cardinality of a data type to be more restrictive (e.g. changing an
|
||||
* {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL
|
||||
* OPTIONAL} property into a
|
||||
* {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED
|
||||
* REQUIRED} property).
|
||||
* <li>Adding a
|
||||
* {@link android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED
|
||||
* REQUIRED} property.
|
||||
* <li>Removal of an existing type
|
||||
* <li>Removal of a property from a type
|
||||
* <li>Changing the data type ({@code boolean}, {@code long}, etc.) of an existing property
|
||||
* <li>For properties of {@code GenericDocument} type, changing the schema type of {@code
|
||||
* GenericDocument}s of that property
|
||||
* <li>Changing the cardinality of a data type to be more restrictive (e.g. changing an {@link
|
||||
* android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_OPTIONAL OPTIONAL}
|
||||
* property into a {@link
|
||||
* android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED}
|
||||
* property).
|
||||
* <li>Adding a {@link
|
||||
* android.app.appsearch.AppSearchSchema.PropertyConfig#CARDINALITY_REQUIRED REQUIRED}
|
||||
* property.
|
||||
* </ul>
|
||||
* <p>Supplying a schema with such changes will result in this call returning an
|
||||
* {@link AppSearchResult} with a code of {@link AppSearchResult#RESULT_INVALID_SCHEMA} and an
|
||||
* error message describing the incompatibility. In this case the previously set schema will
|
||||
* remain active.
|
||||
*
|
||||
* <p>Supplying a schema with such changes will result in this call returning an {@link
|
||||
* AppSearchResult} with a code of {@link AppSearchResult#RESULT_INVALID_SCHEMA} and an error
|
||||
* message describing the incompatibility. In this case the previously set schema will remain
|
||||
* active.
|
||||
*
|
||||
* <p>If you need to make non-backwards-compatible changes as described above, instead use the
|
||||
* {@link #setSchema(List, boolean)} method with the {@code forceOverride} parameter set to
|
||||
@@ -214,8 +222,8 @@ public class AppSearchManager {
|
||||
*
|
||||
* @param request The schema update request.
|
||||
* @return the result of performing this operation.
|
||||
* @deprecated use {@link AppSearchSession#setSchema} instead.
|
||||
* @hide
|
||||
* @deprecated use {@link AppSearchSession#setSchema} instead.
|
||||
*/
|
||||
@NonNull
|
||||
public AppSearchResult<Void> setSchema(@NonNull SetSchemaRequest request) {
|
||||
@@ -229,6 +237,7 @@ public class AppSearchManager {
|
||||
AndroidFuture<AppSearchResult> future = new AndroidFuture<>();
|
||||
try {
|
||||
mService.setSchema(
|
||||
getPackageName(),
|
||||
DEFAULT_DATABASE_NAME,
|
||||
schemaBundles,
|
||||
new ArrayList<>(request.getSchemasNotVisibleToSystemUi()),
|
||||
@@ -249,21 +258,19 @@ public class AppSearchManager {
|
||||
/**
|
||||
* Index {@link GenericDocument}s into AppSearch.
|
||||
*
|
||||
* <p>You should not call this method directly; instead, use the
|
||||
* {@code AppSearch#putDocuments()} API provided by JetPack.
|
||||
* <p>You should not call this method directly; instead, use the {@code
|
||||
* AppSearch#putDocuments()} API provided by JetPack.
|
||||
*
|
||||
* <p>Each {@link GenericDocument}'s {@code schemaType} field must be set to the name of a
|
||||
* schema type previously registered via the {@link #setSchema} method.
|
||||
*
|
||||
* @param request {@link PutDocumentsRequest} containing documents to be indexed
|
||||
* @return The pending result of performing this operation. The keys of the returned
|
||||
* {@link AppSearchBatchResult} are the URIs of the input documents. The values are
|
||||
* {@code null} if they were successfully indexed, or a failed {@link AppSearchResult}
|
||||
* otherwise.
|
||||
* @return The pending result of performing this operation. The keys of the returned {@link
|
||||
* AppSearchBatchResult} are the URIs of the input documents. The values are {@code null} if
|
||||
* they were successfully indexed, or a failed {@link AppSearchResult} otherwise.
|
||||
* @throws RuntimeException If an error occurred during the execution.
|
||||
*
|
||||
* @deprecated use {@link AppSearchSession#putDocuments} instead.
|
||||
* @hide
|
||||
* @deprecated use {@link AppSearchSession#putDocuments} instead.
|
||||
*/
|
||||
public AppSearchBatchResult<String, Void> putDocuments(@NonNull PutDocumentsRequest request) {
|
||||
// TODO(b/146386470): Transmit these documents as a RemoteStream instead of sending them in
|
||||
@@ -275,7 +282,11 @@ public class AppSearchManager {
|
||||
}
|
||||
AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
|
||||
try {
|
||||
mService.putDocuments(DEFAULT_DATABASE_NAME, documentBundles, mContext.getUserId(),
|
||||
mService.putDocuments(
|
||||
getPackageName(),
|
||||
DEFAULT_DATABASE_NAME,
|
||||
documentBundles,
|
||||
mContext.getUserId(),
|
||||
new IAppSearchBatchResultCallback.Stub() {
|
||||
public void onResult(AppSearchBatchResult result) {
|
||||
future.complete(result);
|
||||
@@ -294,19 +305,18 @@ public class AppSearchManager {
|
||||
/**
|
||||
* Retrieves {@link GenericDocument}s by URI.
|
||||
*
|
||||
* <p>You should not call this method directly; instead, use the
|
||||
* {@code AppSearch#getDocuments()} API provided by JetPack.
|
||||
* <p>You should not call this method directly; instead, use the {@code
|
||||
* AppSearch#getDocuments()} API provided by JetPack.
|
||||
*
|
||||
* @param request {@link GetByUriRequest} containing URIs to be retrieved.
|
||||
* @return The pending result of performing this operation. The keys of the returned
|
||||
* {@link AppSearchBatchResult} are the input URIs. The values are the returned
|
||||
* {@link GenericDocument}s 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}.
|
||||
* @return The pending result of performing this operation. The keys of the returned {@link
|
||||
* AppSearchBatchResult} are the input URIs. The values are the returned {@link
|
||||
* GenericDocument}s 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}.
|
||||
* @throws RuntimeException If an error occurred during the execution.
|
||||
*
|
||||
* @deprecated use {@link AppSearchSession#getByUri} instead.
|
||||
* @hide
|
||||
* @deprecated use {@link AppSearchSession#getByUri} instead.
|
||||
*/
|
||||
public AppSearchBatchResult<String, GenericDocument> getByUri(
|
||||
@NonNull GetByUriRequest request) {
|
||||
@@ -315,7 +325,11 @@ public class AppSearchManager {
|
||||
List<String> uris = new ArrayList<>(request.getUris());
|
||||
AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
|
||||
try {
|
||||
mService.getDocuments(DEFAULT_DATABASE_NAME, request.getNamespace(), uris,
|
||||
mService.getDocuments(
|
||||
getPackageName(),
|
||||
DEFAULT_DATABASE_NAME,
|
||||
request.getNamespace(),
|
||||
uris,
|
||||
mContext.getUserId(),
|
||||
new IAppSearchBatchResultCallback.Stub() {
|
||||
public void onResult(AppSearchBatchResult result) {
|
||||
@@ -371,43 +385,39 @@ public class AppSearchManager {
|
||||
* provided by JetPack.
|
||||
*
|
||||
* <p>Currently we support following features in the raw query format:
|
||||
*
|
||||
* <ul>
|
||||
* <li>AND
|
||||
* <p>AND joins (e.g. “match documents that have both the terms ‘dog’ and
|
||||
* ‘cat’”).
|
||||
* Example: hello world matches documents that have both ‘hello’ and ‘world’
|
||||
* <li>OR
|
||||
* <p>OR joins (e.g. “match documents that have either the term ‘dog’ or
|
||||
* ‘cat’”).
|
||||
* Example: dog OR puppy
|
||||
* <li>Exclusion
|
||||
* <p>Exclude a term (e.g. “match documents that do
|
||||
* not have the term ‘dog’”).
|
||||
* Example: -dog excludes the term ‘dog’
|
||||
* <li>Grouping terms
|
||||
* <p>Allow for conceptual grouping of subqueries to enable hierarchical structures (e.g.
|
||||
* “match documents that have either ‘dog’ or ‘puppy’, and either ‘cat’ or ‘kitten’”).
|
||||
* Example: (dog puppy) (cat kitten) two one group containing two terms.
|
||||
* <li>Property restricts
|
||||
* <p> Specifies which properties of a document to specifically match terms in (e.g.
|
||||
* “match documents where the ‘subject’ property contains ‘important’”).
|
||||
* Example: subject:important matches documents with the term ‘important’ in the
|
||||
* ‘subject’ property
|
||||
* <li>Schema type restricts
|
||||
* <p>This is similar to property restricts, but allows for restricts on top-level document
|
||||
* fields, such as schema_type. Clients should be able to limit their query to documents of
|
||||
* a certain schema_type (e.g. “match documents that are of the ‘Email’ schema_type”).
|
||||
* Example: { schema_type_filters: “Email”, “Video”,query: “dog” } will match documents
|
||||
* that contain the query term ‘dog’ and are of either the ‘Email’ schema type or the
|
||||
* ‘Video’ schema type.
|
||||
* <li>AND
|
||||
* <p>AND joins (e.g. “match documents that have both the terms ‘dog’ and ‘cat’”).
|
||||
* Example: hello world matches documents that have both ‘hello’ and ‘world’
|
||||
* <li>OR
|
||||
* <p>OR joins (e.g. “match documents that have either the term ‘dog’ or ‘cat’”). Example:
|
||||
* dog OR puppy
|
||||
* <li>Exclusion
|
||||
* <p>Exclude a term (e.g. “match documents that do not have the term ‘dog’”). Example:
|
||||
* -dog excludes the term ‘dog’
|
||||
* <li>Grouping terms
|
||||
* <p>Allow for conceptual grouping of subqueries to enable hierarchical structures (e.g.
|
||||
* “match documents that have either ‘dog’ or ‘puppy’, and either ‘cat’ or ‘kitten’”).
|
||||
* Example: (dog puppy) (cat kitten) two one group containing two terms.
|
||||
* <li>Property restricts
|
||||
* <p>Specifies which properties of a document to specifically match terms in (e.g. “match
|
||||
* documents where the ‘subject’ property contains ‘important’”). Example:
|
||||
* subject:important matches documents with the term ‘important’ in the ‘subject’ property
|
||||
* <li>Schema type restricts
|
||||
* <p>This is similar to property restricts, but allows for restricts on top-level
|
||||
* document fields, such as schema_type. Clients should be able to limit their query to
|
||||
* documents of a certain schema_type (e.g. “match documents that are of the ‘Email’
|
||||
* schema_type”). Example: { schema_type_filters: “Email”, “Video”,query: “dog” } will
|
||||
* match documents that contain the query term ‘dog’ and are of either the ‘Email’ schema
|
||||
* type or the ‘Video’ schema type.
|
||||
* </ul>
|
||||
*
|
||||
* @param queryExpression Query String to search.
|
||||
* @param searchSpec Spec for setting filters, raw query etc.
|
||||
* @throws RuntimeException If an error occurred during the execution.
|
||||
*
|
||||
* @deprecated use AppSearchSession#query instead.
|
||||
* @hide
|
||||
* @deprecated use AppSearchSession#query instead.
|
||||
*/
|
||||
@NonNull
|
||||
public AppSearchResult<List<SearchResult>> query(
|
||||
@@ -416,7 +426,11 @@ public class AppSearchManager {
|
||||
// them in one big list.
|
||||
AndroidFuture<AppSearchResult> future = new AndroidFuture<>();
|
||||
try {
|
||||
mService.query(DEFAULT_DATABASE_NAME, queryExpression, searchSpec.getBundle(),
|
||||
mService.query(
|
||||
getPackageName(),
|
||||
DEFAULT_DATABASE_NAME,
|
||||
queryExpression,
|
||||
searchSpec.getBundle(),
|
||||
mContext.getUserId(),
|
||||
new IAppSearchResultCallback.Stub() {
|
||||
public void onResult(AppSearchResult result) {
|
||||
@@ -425,8 +439,8 @@ public class AppSearchManager {
|
||||
});
|
||||
AppSearchResult<Bundle> bundleResult = getFutureOrThrow(future);
|
||||
if (!bundleResult.isSuccess()) {
|
||||
return AppSearchResult.newFailedResult(bundleResult.getResultCode(),
|
||||
bundleResult.getErrorMessage());
|
||||
return AppSearchResult.newFailedResult(
|
||||
bundleResult.getResultCode(), bundleResult.getErrorMessage());
|
||||
}
|
||||
SearchResultPage searchResultPage = new SearchResultPage(bundleResult.getResultValue());
|
||||
return AppSearchResult.newSuccessfulResult(searchResultPage.getResults());
|
||||
@@ -444,21 +458,23 @@ public class AppSearchManager {
|
||||
* provided by JetPack.
|
||||
*
|
||||
* @param request Request containing URIs to be removed.
|
||||
* @return 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}.
|
||||
* @return 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}.
|
||||
* @throws RuntimeException If an error occurred during the execution.
|
||||
*
|
||||
* @deprecated use {@link AppSearchSession#removeByUri} instead.
|
||||
* @hide
|
||||
* @deprecated use {@link AppSearchSession#removeByUri} instead.
|
||||
*/
|
||||
public AppSearchBatchResult<String, Void> removeByUri(@NonNull RemoveByUriRequest request) {
|
||||
List<String> uris = new ArrayList<>(request.getUris());
|
||||
AndroidFuture<AppSearchBatchResult> future = new AndroidFuture<>();
|
||||
try {
|
||||
mService.removeByUri(DEFAULT_DATABASE_NAME, request.getNamespace(), uris,
|
||||
mService.removeByUri(
|
||||
getPackageName(),
|
||||
DEFAULT_DATABASE_NAME,
|
||||
request.getNamespace(),
|
||||
uris,
|
||||
mContext.getUserId(),
|
||||
new IAppSearchBatchResultCallback.Stub() {
|
||||
public void onResult(AppSearchBatchResult result) {
|
||||
@@ -475,6 +491,12 @@ public class AppSearchManager {
|
||||
return getFutureOrThrow(future);
|
||||
}
|
||||
|
||||
/** Returns the package name that should be used for uid verification. */
|
||||
@NonNull
|
||||
private String getPackageName() {
|
||||
return mContext.getOpPackageName();
|
||||
}
|
||||
|
||||
private static <T> T getFutureOrThrow(@NonNull AndroidFuture<T> future) {
|
||||
try {
|
||||
return future.get();
|
||||
|
||||
@@ -45,6 +45,7 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public final class AppSearchSession implements Closeable {
|
||||
private static final String TAG = "AppSearchSession";
|
||||
private final String mPackageName;
|
||||
private final String mDatabaseName;
|
||||
@UserIdInt
|
||||
private final int mUserId;
|
||||
@@ -52,14 +53,20 @@ public final class AppSearchSession implements Closeable {
|
||||
private boolean mIsMutated = false;
|
||||
private boolean mIsClosed = false;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a search session for the client, defined by the {@code userId} and
|
||||
* {@code packageName}.
|
||||
*/
|
||||
static void createSearchSession(
|
||||
@NonNull AppSearchManager.SearchContext searchContext,
|
||||
@NonNull IAppSearchManager service,
|
||||
@UserIdInt int userId,
|
||||
@NonNull String packageName,
|
||||
@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull Consumer<AppSearchResult<AppSearchSession>> callback) {
|
||||
AppSearchSession searchSession =
|
||||
new AppSearchSession(service, userId, searchContext.mDatabaseName);
|
||||
new AppSearchSession(service, userId, packageName, searchContext.mDatabaseName);
|
||||
searchSession.initialize(executor, callback);
|
||||
}
|
||||
|
||||
@@ -87,10 +94,11 @@ public final class AppSearchSession implements Closeable {
|
||||
}
|
||||
|
||||
private AppSearchSession(@NonNull IAppSearchManager service, @UserIdInt int userId,
|
||||
@NonNull String databaseName) {
|
||||
mDatabaseName = databaseName;
|
||||
@NonNull String packageName, @NonNull String databaseName) {
|
||||
mService = service;
|
||||
mUserId = userId;
|
||||
mPackageName = packageName;
|
||||
mDatabaseName = databaseName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,7 +152,7 @@ public final class AppSearchSession implements Closeable {
|
||||
* Visibility settings for a schema type do not apply or persist across
|
||||
* {@link SetSchemaRequest}s.
|
||||
*
|
||||
* @param request The schema update request.
|
||||
* @param request The schema update request.
|
||||
* @param executor Executor on which to invoke the callback.
|
||||
* @param callback Callback to receive errors resulting from setting the schema. If the
|
||||
* operation succeeds, the callback will be invoked with {@code null}.
|
||||
@@ -175,6 +183,7 @@ public final class AppSearchSession implements Closeable {
|
||||
}
|
||||
try {
|
||||
mService.setSchema(
|
||||
mPackageName,
|
||||
mDatabaseName,
|
||||
schemaBundles,
|
||||
new ArrayList<>(request.getSchemasNotVisibleToSystemUi()),
|
||||
@@ -206,6 +215,7 @@ public final class AppSearchSession implements Closeable {
|
||||
Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
|
||||
try {
|
||||
mService.getSchema(
|
||||
mPackageName,
|
||||
mDatabaseName,
|
||||
mUserId,
|
||||
new IAppSearchResultCallback.Stub() {
|
||||
@@ -261,7 +271,7 @@ public final class AppSearchSession implements Closeable {
|
||||
documentBundles.add(documents.get(i).getBundle());
|
||||
}
|
||||
try {
|
||||
mService.putDocuments(mDatabaseName, documentBundles, mUserId,
|
||||
mService.putDocuments(mPackageName, mDatabaseName, documentBundles, mUserId,
|
||||
new IAppSearchBatchResultCallback.Stub() {
|
||||
public void onResult(AppSearchBatchResult result) {
|
||||
executor.execute(() -> callback.onResult(result));
|
||||
@@ -280,7 +290,7 @@ public final class AppSearchSession implements Closeable {
|
||||
/**
|
||||
* Retrieves {@link GenericDocument}s by URI.
|
||||
*
|
||||
* @param request {@link GetByUriRequest} containing URIs to be retrieved.
|
||||
* @param request {@link GetByUriRequest} containing URIs to be retrieved.
|
||||
* @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
|
||||
@@ -301,7 +311,7 @@ public final class AppSearchSession implements Closeable {
|
||||
Objects.requireNonNull(callback);
|
||||
Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
|
||||
try {
|
||||
mService.getDocuments(mDatabaseName, request.getNamespace(),
|
||||
mService.getDocuments(mPackageName, mDatabaseName, request.getNamespace(),
|
||||
new ArrayList<>(request.getUris()), mUserId,
|
||||
new IAppSearchBatchResultCallback.Stub() {
|
||||
public void onResult(AppSearchBatchResult result) {
|
||||
@@ -405,14 +415,14 @@ public final class AppSearchSession implements Closeable {
|
||||
Objects.requireNonNull(searchSpec);
|
||||
Objects.requireNonNull(executor);
|
||||
Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
|
||||
return new SearchResults(mService, mDatabaseName, queryExpression, searchSpec, mUserId,
|
||||
executor);
|
||||
return new SearchResults(mService, mPackageName, mDatabaseName, queryExpression,
|
||||
searchSpec, mUserId, executor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes {@link GenericDocument}s from the index by URI.
|
||||
*
|
||||
* @param request Request containing URIs to be removed.
|
||||
* @param request Request containing URIs to be removed.
|
||||
* @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
|
||||
@@ -432,7 +442,7 @@ public final class AppSearchSession implements Closeable {
|
||||
Objects.requireNonNull(callback);
|
||||
Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
|
||||
try {
|
||||
mService.removeByUri(mDatabaseName, request.getNamespace(),
|
||||
mService.removeByUri(mPackageName, mDatabaseName, request.getNamespace(),
|
||||
new ArrayList<>(request.getUris()), mUserId,
|
||||
new IAppSearchBatchResultCallback.Stub() {
|
||||
public void onResult(AppSearchBatchResult result) {
|
||||
@@ -478,7 +488,8 @@ public final class AppSearchSession implements Closeable {
|
||||
Objects.requireNonNull(callback);
|
||||
Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
|
||||
try {
|
||||
mService.removeByQuery(mDatabaseName, queryExpression, searchSpec.getBundle(), mUserId,
|
||||
mService.removeByQuery(mPackageName, mDatabaseName, queryExpression,
|
||||
searchSpec.getBundle(), mUserId,
|
||||
new IAppSearchResultCallback.Stub() {
|
||||
public void onResult(AppSearchResult result) {
|
||||
executor.execute(() -> callback.accept(result));
|
||||
|
||||
@@ -37,16 +37,25 @@ import java.util.function.Consumer;
|
||||
public class GlobalSearchSession implements Closeable {
|
||||
|
||||
private final IAppSearchManager mService;
|
||||
|
||||
@UserIdInt
|
||||
private final int mUserId;
|
||||
private boolean mIsClosed = false;
|
||||
|
||||
private final String mPackageName;
|
||||
|
||||
/**
|
||||
* Creates a search session for the client, defined by the {@code userId} and
|
||||
* {@code packageName}.
|
||||
*/
|
||||
static void createGlobalSearchSession(
|
||||
@NonNull IAppSearchManager service,
|
||||
@UserIdInt int userId,
|
||||
@NonNull String packageName,
|
||||
@NonNull @CallbackExecutor Executor executor,
|
||||
@NonNull Consumer<AppSearchResult<GlobalSearchSession>> callback) {
|
||||
GlobalSearchSession globalSearchSession = new GlobalSearchSession(service, userId);
|
||||
GlobalSearchSession globalSearchSession = new GlobalSearchSession(service, userId,
|
||||
packageName);
|
||||
globalSearchSession.initialize(executor, callback);
|
||||
}
|
||||
|
||||
@@ -73,9 +82,11 @@ public class GlobalSearchSession implements Closeable {
|
||||
}
|
||||
}
|
||||
|
||||
private GlobalSearchSession(@NonNull IAppSearchManager service, @UserIdInt int userId) {
|
||||
private GlobalSearchSession(@NonNull IAppSearchManager service, @UserIdInt int userId,
|
||||
@NonNull String packageName) {
|
||||
mService = service;
|
||||
mUserId = userId;
|
||||
mPackageName = packageName;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,7 +142,7 @@ public class GlobalSearchSession implements Closeable {
|
||||
Objects.requireNonNull(searchSpec);
|
||||
Objects.requireNonNull(executor);
|
||||
Preconditions.checkState(!mIsClosed, "GlobalSearchSession has already been closed");
|
||||
return new SearchResults(mService, /*databaseName=*/null, queryExpression,
|
||||
return new SearchResults(mService, mPackageName, /*databaseName=*/null, queryExpression,
|
||||
searchSpec, mUserId, executor);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ interface IAppSearchManager {
|
||||
/**
|
||||
* Updates the AppSearch schema for this database.
|
||||
*
|
||||
* @param packageName The name of the package that owns this schema.
|
||||
* @param databaseName The name of the database where this schema lives.
|
||||
* @param schemaBundles List of {@link AppSearchSchema} bundles.
|
||||
* @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
|
||||
@@ -43,6 +44,7 @@ interface IAppSearchManager {
|
||||
* {@link AppSearchResult}<{@link Void}>.
|
||||
*/
|
||||
void setSchema(
|
||||
in String packageName,
|
||||
in String databaseName,
|
||||
in List<Bundle> schemaBundles,
|
||||
in List<String> schemasNotPlatformSurfaceable,
|
||||
@@ -54,17 +56,23 @@ interface IAppSearchManager {
|
||||
/**
|
||||
* Retrieves the AppSearch schema for this database.
|
||||
*
|
||||
* @param packageName The name of the package that owns the schema.
|
||||
* @param databaseName The name of the database to retrieve.
|
||||
* @param userId Id of the calling user
|
||||
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
|
||||
* {@link AppSearchResult}<{@link List}<{@link Bundle}>>, where the value are
|
||||
* AppSearchSchema bundle.
|
||||
*/
|
||||
void getSchema(in String databaseName, in int userId, in IAppSearchResultCallback callback);
|
||||
void getSchema(
|
||||
in String packageName,
|
||||
in String databaseName,
|
||||
in int userId,
|
||||
in IAppSearchResultCallback callback);
|
||||
|
||||
/**
|
||||
* Inserts documents into the index.
|
||||
*
|
||||
* @param packageName The name of the package that owns this document.
|
||||
* @param databaseName The name of the database where this document lives.
|
||||
* @param documentBundes List of GenericDocument bundles.
|
||||
* @param userId Id of the calling user
|
||||
@@ -76,6 +84,7 @@ interface IAppSearchManager {
|
||||
* where the keys are document URIs, and the values are {@code null}.
|
||||
*/
|
||||
void putDocuments(
|
||||
in String packageName,
|
||||
in String databaseName,
|
||||
in List<Bundle> documentBundles,
|
||||
in int userId,
|
||||
@@ -84,6 +93,7 @@ interface IAppSearchManager {
|
||||
/**
|
||||
* Retrieves documents from the index.
|
||||
*
|
||||
* @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
|
||||
@@ -96,6 +106,7 @@ interface IAppSearchManager {
|
||||
* where the keys are document URIs, and the values are Document bundles.
|
||||
*/
|
||||
void getDocuments(
|
||||
in String packageName,
|
||||
in String databaseName,
|
||||
in String namespace,
|
||||
in List<String> uris,
|
||||
@@ -105,6 +116,7 @@ interface IAppSearchManager {
|
||||
/**
|
||||
* Searches a document based on a given specifications.
|
||||
*
|
||||
* @param packageName The name of the package to query over.
|
||||
* @param databaseName The databaseName this query for.
|
||||
* @param queryExpression String to search for
|
||||
* @param searchSpecBundle SearchSpec bundle
|
||||
@@ -113,6 +125,7 @@ interface IAppSearchManager {
|
||||
* operation.
|
||||
*/
|
||||
void query(
|
||||
in String packageName,
|
||||
in String databaseName,
|
||||
in String queryExpression,
|
||||
in Bundle searchSpecBundle,
|
||||
@@ -123,6 +136,7 @@ interface IAppSearchManager {
|
||||
* Executes a global query, i.e. over all permitted databases, against the AppSearch index and
|
||||
* returns results.
|
||||
*
|
||||
* @param packageName The name of the package making the query.
|
||||
* @param queryExpression String to search for
|
||||
* @param searchSpecBundle SearchSpec bundle
|
||||
* @param userId Id of the calling user
|
||||
@@ -130,6 +144,7 @@ interface IAppSearchManager {
|
||||
* operation.
|
||||
*/
|
||||
void globalQuery(
|
||||
in String packageName,
|
||||
in String queryExpression,
|
||||
in Bundle searchSpecBundle,
|
||||
in int userId,
|
||||
@@ -158,6 +173,7 @@ interface IAppSearchManager {
|
||||
/**
|
||||
* Removes documents by URI.
|
||||
*
|
||||
* @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
|
||||
@@ -171,6 +187,7 @@ interface IAppSearchManager {
|
||||
* failure where the {@code throwable} is {@code null}.
|
||||
*/
|
||||
void removeByUri(
|
||||
in String packageName,
|
||||
in String databaseName,
|
||||
in String namespace,
|
||||
in List<String> uris,
|
||||
@@ -180,6 +197,7 @@ interface IAppSearchManager {
|
||||
/**
|
||||
* Removes documents by given query.
|
||||
*
|
||||
* @param packageName The name of the package to query over.
|
||||
* @param databaseName The databaseName this query for.
|
||||
* @param queryExpression String to search for
|
||||
* @param searchSpecBundle SearchSpec bundle
|
||||
@@ -188,6 +206,7 @@ interface IAppSearchManager {
|
||||
* {@link AppSearchResult}<{@link Void}>.
|
||||
*/
|
||||
void removeByQuery(
|
||||
in String packageName,
|
||||
in String databaseName,
|
||||
in String queryExpression,
|
||||
in Bundle searchSpecBundle,
|
||||
|
||||
@@ -47,6 +47,9 @@ public class SearchResults implements Closeable {
|
||||
|
||||
private final IAppSearchManager mService;
|
||||
|
||||
// The package name of the caller.
|
||||
private final String mPackageName;
|
||||
|
||||
// The database name to search over. If null, this will search over all database names.
|
||||
@Nullable
|
||||
private final String mDatabaseName;
|
||||
@@ -68,12 +71,14 @@ public class SearchResults implements Closeable {
|
||||
|
||||
SearchResults(
|
||||
@NonNull IAppSearchManager service,
|
||||
@NonNull String packageName,
|
||||
@Nullable String databaseName,
|
||||
@NonNull String queryExpression,
|
||||
@NonNull SearchSpec searchSpec,
|
||||
@UserIdInt int userId,
|
||||
@NonNull @CallbackExecutor Executor executor) {
|
||||
mService = Objects.requireNonNull(service);
|
||||
mPackageName = packageName;
|
||||
mDatabaseName = databaseName;
|
||||
mQueryExpression = Objects.requireNonNull(queryExpression);
|
||||
mSearchSpec = Objects.requireNonNull(searchSpec);
|
||||
@@ -98,13 +103,12 @@ public class SearchResults implements Closeable {
|
||||
mIsFirstLoad = false;
|
||||
if (mDatabaseName == null) {
|
||||
// Global query, there's no one package-database combination to check.
|
||||
mService.globalQuery(mQueryExpression, mSearchSpec.getBundle(), mUserId,
|
||||
wrapCallback(callback));
|
||||
mService.globalQuery(mPackageName, mQueryExpression,
|
||||
mSearchSpec.getBundle(), mUserId, wrapCallback(callback));
|
||||
} else {
|
||||
// Normal local query, pass in specified database.
|
||||
mService.query(
|
||||
mDatabaseName, mQueryExpression, mSearchSpec.getBundle(), mUserId,
|
||||
wrapCallback(callback));
|
||||
mService.query(mPackageName, mDatabaseName, mQueryExpression,
|
||||
mSearchSpec.getBundle(), mUserId, wrapCallback(callback));
|
||||
}
|
||||
} else {
|
||||
mService.getNextPage(mNextPageToken, mUserId, wrapCallback(callback));
|
||||
|
||||
@@ -31,14 +31,17 @@ import android.app.appsearch.PackageIdentifier;
|
||||
import android.app.appsearch.SearchResultPage;
|
||||
import android.app.appsearch.SearchSpec;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelableException;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
|
||||
|
||||
@@ -46,11 +49,10 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TODO(b/142567528): add comments when implement this class
|
||||
*/
|
||||
/** TODO(b/142567528): add comments when implement this class */
|
||||
public class AppSearchManagerService extends SystemService {
|
||||
private static final String TAG = "AppSearchManagerService";
|
||||
private PackageManagerInternal mPackageManagerInternal;
|
||||
|
||||
public AppSearchManagerService(Context context) {
|
||||
super(context);
|
||||
@@ -59,11 +61,13 @@ public class AppSearchManagerService extends SystemService {
|
||||
@Override
|
||||
public void onStart() {
|
||||
publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
|
||||
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
|
||||
}
|
||||
|
||||
private class Stub extends IAppSearchManager.Stub {
|
||||
@Override
|
||||
public void setSchema(
|
||||
@NonNull String packageName,
|
||||
@NonNull String databaseName,
|
||||
@NonNull List<Bundle> schemaBundles,
|
||||
@NonNull List<String> schemasNotPlatformSurfaceable,
|
||||
@@ -71,6 +75,7 @@ public class AppSearchManagerService extends SystemService {
|
||||
boolean forceOverride,
|
||||
@UserIdInt int userId,
|
||||
@NonNull IAppSearchResultCallback callback) {
|
||||
Preconditions.checkNotNull(packageName);
|
||||
Preconditions.checkNotNull(databaseName);
|
||||
Preconditions.checkNotNull(schemaBundles);
|
||||
Preconditions.checkNotNull(callback);
|
||||
@@ -78,6 +83,7 @@ public class AppSearchManagerService extends SystemService {
|
||||
int callingUserId = handleIncomingUser(userId, callingUid);
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
|
||||
for (int i = 0; i < schemaBundles.size(); i++) {
|
||||
schemas.add(new AppSearchSchema(schemaBundles.get(i)));
|
||||
@@ -94,7 +100,6 @@ public class AppSearchManagerService extends SystemService {
|
||||
schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
|
||||
}
|
||||
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
|
||||
String packageName = convertUidToPackageName(callingUid);
|
||||
impl.setSchema(
|
||||
packageName,
|
||||
databaseName,
|
||||
@@ -102,8 +107,8 @@ public class AppSearchManagerService extends SystemService {
|
||||
schemasNotPlatformSurfaceable,
|
||||
schemasPackageAccessible,
|
||||
forceOverride);
|
||||
invokeCallbackOnResult(callback,
|
||||
AppSearchResult.newSuccessfulResult(/*result=*/ null));
|
||||
invokeCallbackOnResult(
|
||||
callback, AppSearchResult.newSuccessfulResult(/*result=*/ null));
|
||||
} catch (Throwable t) {
|
||||
invokeCallbackOnError(callback, t);
|
||||
} finally {
|
||||
@@ -113,24 +118,26 @@ public class AppSearchManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void getSchema(
|
||||
@NonNull String packageName,
|
||||
@NonNull String databaseName,
|
||||
@UserIdInt int userId,
|
||||
@NonNull IAppSearchResultCallback callback) {
|
||||
Preconditions.checkNotNull(packageName);
|
||||
Preconditions.checkNotNull(databaseName);
|
||||
Preconditions.checkNotNull(callback);
|
||||
int callingUid = Binder.getCallingUidOrThrow();
|
||||
int callingUserId = handleIncomingUser(userId, callingUid);
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
|
||||
String packageName = convertUidToPackageName(callingUid);
|
||||
List<AppSearchSchema> schemas = impl.getSchema(packageName, databaseName);
|
||||
List<Bundle> schemaBundles = new ArrayList<>(schemas.size());
|
||||
for (int i = 0; i < schemas.size(); i++) {
|
||||
schemaBundles.add(schemas.get(i).getBundle());
|
||||
}
|
||||
invokeCallbackOnResult(callback,
|
||||
AppSearchResult.newSuccessfulResult(schemaBundles));
|
||||
invokeCallbackOnResult(
|
||||
callback, AppSearchResult.newSuccessfulResult(schemaBundles));
|
||||
} catch (Throwable t) {
|
||||
invokeCallbackOnError(callback, t);
|
||||
} finally {
|
||||
@@ -140,10 +147,12 @@ public class AppSearchManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void putDocuments(
|
||||
@NonNull String packageName,
|
||||
@NonNull String databaseName,
|
||||
@NonNull List<Bundle> documentBundles,
|
||||
@UserIdInt int userId,
|
||||
@NonNull IAppSearchBatchResultCallback callback) {
|
||||
Preconditions.checkNotNull(packageName);
|
||||
Preconditions.checkNotNull(databaseName);
|
||||
Preconditions.checkNotNull(documentBundles);
|
||||
Preconditions.checkNotNull(callback);
|
||||
@@ -151,10 +160,10 @@ public class AppSearchManagerService extends SystemService {
|
||||
int callingUserId = handleIncomingUser(userId, callingUid);
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
AppSearchBatchResult.Builder<String, Void> resultBuilder =
|
||||
new AppSearchBatchResult.Builder<>();
|
||||
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
|
||||
String packageName = convertUidToPackageName(callingUid);
|
||||
for (int i = 0; i < documentBundles.size(); i++) {
|
||||
GenericDocument document = new GenericDocument(documentBundles.get(i));
|
||||
try {
|
||||
@@ -176,11 +185,13 @@ public class AppSearchManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void getDocuments(
|
||||
@NonNull String packageName,
|
||||
@NonNull String databaseName,
|
||||
@NonNull String namespace,
|
||||
@NonNull List<String> uris,
|
||||
@UserIdInt int userId,
|
||||
@NonNull IAppSearchBatchResultCallback callback) {
|
||||
Preconditions.checkNotNull(packageName);
|
||||
Preconditions.checkNotNull(databaseName);
|
||||
Preconditions.checkNotNull(namespace);
|
||||
Preconditions.checkNotNull(uris);
|
||||
@@ -189,15 +200,15 @@ public class AppSearchManagerService extends SystemService {
|
||||
int callingUserId = handleIncomingUser(userId, callingUid);
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
|
||||
new AppSearchBatchResult.Builder<>();
|
||||
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
|
||||
String packageName = convertUidToPackageName(callingUid);
|
||||
for (int i = 0; i < uris.size(); i++) {
|
||||
String uri = uris.get(i);
|
||||
try {
|
||||
GenericDocument document = impl.getDocument(packageName, databaseName,
|
||||
namespace, uri);
|
||||
GenericDocument document =
|
||||
impl.getDocument(packageName, databaseName, namespace, uri);
|
||||
resultBuilder.setSuccess(uri, document.getBundle());
|
||||
} catch (Throwable t) {
|
||||
resultBuilder.setResult(uri, throwableToFailedResult(t));
|
||||
@@ -214,11 +225,13 @@ public class AppSearchManagerService extends SystemService {
|
||||
// TODO(sidchhabra): Do this in a threadpool.
|
||||
@Override
|
||||
public void query(
|
||||
@NonNull String packageName,
|
||||
@NonNull String databaseName,
|
||||
@NonNull String queryExpression,
|
||||
@NonNull Bundle searchSpecBundle,
|
||||
@UserIdInt int userId,
|
||||
@NonNull IAppSearchResultCallback callback) {
|
||||
Preconditions.checkNotNull(packageName);
|
||||
Preconditions.checkNotNull(databaseName);
|
||||
Preconditions.checkNotNull(queryExpression);
|
||||
Preconditions.checkNotNull(searchSpecBundle);
|
||||
@@ -227,14 +240,16 @@ public class AppSearchManagerService extends SystemService {
|
||||
int callingUserId = handleIncomingUser(userId, callingUid);
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
|
||||
String packageName = convertUidToPackageName(callingUid);
|
||||
SearchResultPage searchResultPage = impl.query(
|
||||
packageName,
|
||||
databaseName,
|
||||
queryExpression,
|
||||
new SearchSpec(searchSpecBundle));
|
||||
invokeCallbackOnResult(callback,
|
||||
SearchResultPage searchResultPage =
|
||||
impl.query(
|
||||
packageName,
|
||||
databaseName,
|
||||
queryExpression,
|
||||
new SearchSpec(searchSpecBundle));
|
||||
invokeCallbackOnResult(
|
||||
callback,
|
||||
AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
|
||||
} catch (Throwable t) {
|
||||
invokeCallbackOnError(callback, t);
|
||||
@@ -245,10 +260,12 @@ public class AppSearchManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void globalQuery(
|
||||
@NonNull String packageName,
|
||||
@NonNull String queryExpression,
|
||||
@NonNull Bundle searchSpecBundle,
|
||||
@UserIdInt int userId,
|
||||
@NonNull IAppSearchResultCallback callback) {
|
||||
Preconditions.checkNotNull(packageName);
|
||||
Preconditions.checkNotNull(queryExpression);
|
||||
Preconditions.checkNotNull(searchSpecBundle);
|
||||
Preconditions.checkNotNull(callback);
|
||||
@@ -256,11 +273,12 @@ public class AppSearchManagerService extends SystemService {
|
||||
int callingUserId = handleIncomingUser(userId, callingUid);
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
|
||||
SearchResultPage searchResultPage = impl.globalQuery(
|
||||
queryExpression,
|
||||
new SearchSpec(searchSpecBundle));
|
||||
invokeCallbackOnResult(callback,
|
||||
SearchResultPage searchResultPage =
|
||||
impl.globalQuery(queryExpression, new SearchSpec(searchSpecBundle));
|
||||
invokeCallbackOnResult(
|
||||
callback,
|
||||
AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
|
||||
} catch (Throwable t) {
|
||||
invokeCallbackOnError(callback, t);
|
||||
@@ -270,7 +288,9 @@ public class AppSearchManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNextPage(long nextPageToken, @UserIdInt int userId,
|
||||
public void getNextPage(
|
||||
long nextPageToken,
|
||||
@UserIdInt int userId,
|
||||
@NonNull IAppSearchResultCallback callback) {
|
||||
Preconditions.checkNotNull(callback);
|
||||
int callingUid = Binder.getCallingUid();
|
||||
@@ -281,7 +301,8 @@ public class AppSearchManagerService extends SystemService {
|
||||
try {
|
||||
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
|
||||
SearchResultPage searchResultPage = impl.getNextPage(nextPageToken);
|
||||
invokeCallbackOnResult(callback,
|
||||
invokeCallbackOnResult(
|
||||
callback,
|
||||
AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
|
||||
} catch (Throwable t) {
|
||||
invokeCallbackOnError(callback, t);
|
||||
@@ -307,11 +328,13 @@ public class AppSearchManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void removeByUri(
|
||||
@NonNull String packageName,
|
||||
@NonNull String databaseName,
|
||||
@NonNull String namespace,
|
||||
@NonNull List<String> uris,
|
||||
@UserIdInt int userId,
|
||||
@NonNull IAppSearchBatchResultCallback callback) {
|
||||
Preconditions.checkNotNull(packageName);
|
||||
Preconditions.checkNotNull(databaseName);
|
||||
Preconditions.checkNotNull(uris);
|
||||
Preconditions.checkNotNull(callback);
|
||||
@@ -319,15 +342,15 @@ public class AppSearchManagerService extends SystemService {
|
||||
int callingUserId = handleIncomingUser(userId, callingUid);
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
AppSearchBatchResult.Builder<String, Void> resultBuilder =
|
||||
new AppSearchBatchResult.Builder<>();
|
||||
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
|
||||
String packageName = convertUidToPackageName(callingUid);
|
||||
for (int i = 0; i < uris.size(); i++) {
|
||||
String uri = uris.get(i);
|
||||
try {
|
||||
impl.remove(packageName, databaseName, namespace, uri);
|
||||
resultBuilder.setSuccess(uri, /*result= */null);
|
||||
resultBuilder.setSuccess(uri, /*result= */ null);
|
||||
} catch (Throwable t) {
|
||||
resultBuilder.setResult(uri, throwableToFailedResult(t));
|
||||
}
|
||||
@@ -342,11 +365,13 @@ public class AppSearchManagerService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void removeByQuery(
|
||||
@NonNull String packageName,
|
||||
@NonNull String databaseName,
|
||||
@NonNull String queryExpression,
|
||||
@NonNull Bundle searchSpecBundle,
|
||||
@UserIdInt int userId,
|
||||
@NonNull IAppSearchResultCallback callback) {
|
||||
Preconditions.checkNotNull(packageName);
|
||||
Preconditions.checkNotNull(databaseName);
|
||||
Preconditions.checkNotNull(queryExpression);
|
||||
Preconditions.checkNotNull(searchSpecBundle);
|
||||
@@ -355,9 +380,12 @@ public class AppSearchManagerService extends SystemService {
|
||||
int callingUserId = handleIncomingUser(userId, callingUid);
|
||||
final long callingIdentity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
verifyCallingPackage(callingUid, packageName);
|
||||
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
|
||||
String packageName = convertUidToPackageName(callingUid);
|
||||
impl.removeByQuery(packageName, databaseName, queryExpression,
|
||||
impl.removeByQuery(
|
||||
packageName,
|
||||
databaseName,
|
||||
queryExpression,
|
||||
new SearchSpec(searchSpecBundle));
|
||||
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
|
||||
} catch (Throwable t) {
|
||||
@@ -398,28 +426,22 @@ public class AppSearchManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a package name for the given uid.
|
||||
*
|
||||
* <p>The current implementation returns the package name of the app with this uid in a
|
||||
* format like {@code com.example.package} or {@code com.example.sharedname:5678}.
|
||||
*/
|
||||
@NonNull
|
||||
private String convertUidToPackageName(int callingUid) {
|
||||
// For regular apps, this call will return the package name. If callingUid is an
|
||||
// android:sharedUserId, this value may be another type of name and have a :uid suffix.
|
||||
String callingUidName = getContext().getPackageManager().getNameForUid(callingUid);
|
||||
if (callingUidName == null) {
|
||||
// Not sure how this is possible --- maybe app was uninstalled?
|
||||
throw new IllegalStateException(
|
||||
"Failed to look up package name for uid " + callingUid);
|
||||
private void verifyCallingPackage(int callingUid, @NonNull String callingPackage) {
|
||||
Preconditions.checkNotNull(callingPackage);
|
||||
if (mPackageManagerInternal.getPackageUid(
|
||||
callingPackage, /*flags=*/ 0, UserHandle.getUserId(callingUid))
|
||||
!= callingUid) {
|
||||
throw new SecurityException(
|
||||
"Specified calling package ["
|
||||
+ callingPackage
|
||||
+ "] does not match the calling uid "
|
||||
+ callingUid);
|
||||
}
|
||||
return callingUidName;
|
||||
}
|
||||
|
||||
/** Invokes the {@link IAppSearchResultCallback} with the result. */
|
||||
private void invokeCallbackOnResult(IAppSearchResultCallback callback,
|
||||
AppSearchResult<?> result) {
|
||||
private void invokeCallbackOnResult(
|
||||
IAppSearchResultCallback callback, AppSearchResult<?> result) {
|
||||
try {
|
||||
callback.onResult(result);
|
||||
} catch (RemoteException e) {
|
||||
@@ -428,8 +450,8 @@ public class AppSearchManagerService extends SystemService {
|
||||
}
|
||||
|
||||
/** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
|
||||
private void invokeCallbackOnResult(IAppSearchBatchResultCallback callback,
|
||||
AppSearchBatchResult<?, ?> result) {
|
||||
private void invokeCallbackOnResult(
|
||||
IAppSearchBatchResultCallback callback, AppSearchBatchResult<?, ?> result) {
|
||||
try {
|
||||
callback.onResult(result);
|
||||
} catch (RemoteException e) {
|
||||
@@ -455,8 +477,8 @@ public class AppSearchManagerService extends SystemService {
|
||||
*
|
||||
* <p>The throwable is converted to {@link ParcelableException}.
|
||||
*/
|
||||
private void invokeCallbackOnError(IAppSearchBatchResultCallback callback,
|
||||
Throwable throwable) {
|
||||
private void invokeCallbackOnError(
|
||||
IAppSearchBatchResultCallback callback, Throwable throwable) {
|
||||
try {
|
||||
callback.onSystemError(new ParcelableException(throwable));
|
||||
} catch (RemoteException e) {
|
||||
@@ -465,13 +487,18 @@ public class AppSearchManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO(b/173553485) verifying that the caller has permission to access target user's data
|
||||
//TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
|
||||
//TODO(b/173553485) Implement SystemService.onUserStopping()
|
||||
// TODO(b/173553485) verifying that the caller has permission to access target user's data
|
||||
// TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
|
||||
// TODO(b/173553485) Implement SystemService.onUserStopping()
|
||||
private static int handleIncomingUser(@UserIdInt int userId, int callingUid) {
|
||||
int callingPid = Binder.getCallingPid();
|
||||
return ActivityManager.handleIncomingUser(callingPid, callingUid, userId,
|
||||
/*allowAll=*/ false, /*requireFull=*/ false,
|
||||
/*name=*/ null, /*callerPackage=*/ null);
|
||||
return ActivityManager.handleIncomingUser(
|
||||
callingPid,
|
||||
callingUid,
|
||||
userId,
|
||||
/*allowAll=*/ false,
|
||||
/*requireFull=*/ false,
|
||||
/*name=*/ null,
|
||||
/*callerPackage=*/ null);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user