Merge "Remove PackageManagerInternal from AppSearchService." into sc-dev

This commit is contained in:
Alexander Dorokhine
2021-05-20 20:36:04 +00:00
committed by Android (Google) Code Review
12 changed files with 439 additions and 342 deletions

View File

@@ -205,7 +205,7 @@ public class AppSearchManager {
AppSearchSession.createSearchSession(
searchContext,
mService,
mContext.getUser().getIdentifier(),
mContext.getUser(),
getPackageName(),
executor,
callback);
@@ -228,7 +228,7 @@ public class AppSearchManager {
Objects.requireNonNull(executor);
Objects.requireNonNull(callback);
GlobalSearchSession.createGlobalSearchSession(
mService, mContext.getUser().getIdentifier(), getPackageName(), executor, callback);
mService, mContext.getUser(), getPackageName(), executor, callback);
}
/** Returns the package name that should be used for uid verification. */

View File

@@ -21,7 +21,6 @@ import static android.os.ParcelFileDescriptor.MODE_READ_ONLY;
import static android.os.ParcelFileDescriptor.MODE_WRITE_ONLY;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.app.appsearch.aidl.AppSearchResultParcel;
import android.app.appsearch.aidl.IAppSearchManager;
@@ -31,6 +30,7 @@ import android.os.Bundle;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.ArraySet;
import java.io.Closeable;
@@ -57,20 +57,20 @@ public class AppSearchMigrationHelper implements Closeable {
private final IAppSearchManager mService;
private final String mPackageName;
private final String mDatabaseName;
private final int mUserId;
private final UserHandle mUserHandle;
private final File mMigratedFile;
private final Set<String> mDestinationTypes;
private boolean mAreDocumentsMigrated = false;
AppSearchMigrationHelper(@NonNull IAppSearchManager service,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@NonNull String packageName,
@NonNull String databaseName,
@NonNull Set<AppSearchSchema> newSchemas) throws IOException {
mService = Objects.requireNonNull(service);
mUserHandle = Objects.requireNonNull(userHandle);
mPackageName = Objects.requireNonNull(packageName);
mDatabaseName = Objects.requireNonNull(databaseName);
mUserId = userId;
mMigratedFile = File.createTempFile(/*prefix=*/"appsearch", /*suffix=*/null);
mDestinationTypes = new ArraySet<>(newSchemas.size());
for (AppSearchSchema newSchema : newSchemas) {
@@ -105,7 +105,7 @@ public class AppSearchMigrationHelper implements Closeable {
.addFilterSchemas(schemaType)
.setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
.build().getBundle(),
mUserId,
mUserHandle,
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
@@ -145,7 +145,7 @@ public class AppSearchMigrationHelper implements Closeable {
try (ParcelFileDescriptor fileDescriptor =
ParcelFileDescriptor.open(mMigratedFile, MODE_READ_ONLY)) {
CompletableFuture<AppSearchResult<List<Bundle>>> future = new CompletableFuture<>();
mService.putDocumentsFromFile(mPackageName, mDatabaseName, fileDescriptor, mUserId,
mService.putDocumentsFromFile(mPackageName, mDatabaseName, fileDescriptor, mUserHandle,
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {

View File

@@ -18,7 +18,6 @@ package android.app.appsearch;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.appsearch.aidl.AppSearchBatchResultParcel;
import android.app.appsearch.aidl.AppSearchResultParcel;
import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
@@ -30,6 +29,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -61,26 +61,25 @@ public final class AppSearchSession implements Closeable {
private final String mPackageName;
private final String mDatabaseName;
@UserIdInt
private final int mUserId;
private final UserHandle mUserHandle;
private final IAppSearchManager mService;
private boolean mIsMutated = false;
private boolean mIsClosed = false;
/**
* Creates a search session for the client, defined by the {@code userId} and
* Creates a search session for the client, defined by the {@code userHandle} and
* {@code packageName}.
*/
static void createSearchSession(
@NonNull AppSearchManager.SearchContext searchContext,
@NonNull IAppSearchManager service,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@NonNull String packageName,
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<AppSearchSession>> callback) {
AppSearchSession searchSession =
new AppSearchSession(service, userId, packageName, searchContext.mDatabaseName);
new AppSearchSession(service, userHandle, packageName, searchContext.mDatabaseName);
searchSession.initialize(executor, callback);
}
@@ -90,7 +89,8 @@ public final class AppSearchSession implements Closeable {
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<AppSearchSession>> callback) {
try {
mService.initialize(mUserId,
mService.initialize(
mUserHandle,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override
@@ -112,10 +112,10 @@ public final class AppSearchSession implements Closeable {
}
}
private AppSearchSession(@NonNull IAppSearchManager service, @UserIdInt int userId,
private AppSearchSession(@NonNull IAppSearchManager service, @NonNull UserHandle userHandle,
@NonNull String packageName, @NonNull String databaseName) {
mService = service;
mUserId = userId;
mUserHandle = userHandle;
mPackageName = packageName;
mDatabaseName = databaseName;
}
@@ -199,7 +199,7 @@ public final class AppSearchSession implements Closeable {
mService.getSchema(
mPackageName,
mDatabaseName,
mUserId,
mUserHandle,
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
@@ -236,7 +236,7 @@ public final class AppSearchSession implements Closeable {
mService.getNamespaces(
mPackageName,
mDatabaseName,
mUserId,
mUserHandle,
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
@@ -289,7 +289,7 @@ public final class AppSearchSession implements Closeable {
documentBundles.add(documents.get(i).getBundle());
}
try {
mService.putDocuments(mPackageName, mDatabaseName, documentBundles, mUserId,
mService.putDocuments(mPackageName, mDatabaseName, documentBundles, mUserHandle,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchBatchResultCallback.Stub() {
@Override
@@ -352,7 +352,7 @@ public final class AppSearchSession implements Closeable {
request.getNamespace(),
new ArrayList<>(request.getIds()),
request.getProjectionsInternal(),
mUserId,
mUserHandle,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchBatchResultCallback.Stub() {
@Override
@@ -472,7 +472,7 @@ public final class AppSearchSession implements Closeable {
Objects.requireNonNull(searchSpec);
Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
return new SearchResults(mService, mPackageName, mDatabaseName, queryExpression,
searchSpec, mUserId);
searchSpec, mUserHandle);
}
/**
@@ -508,7 +508,7 @@ public final class AppSearchSession implements Closeable {
request.getDocumentId(),
request.getUsageTimestampMillis(),
/*systemUsage=*/ false,
mUserId,
mUserHandle,
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
@@ -565,8 +565,12 @@ public final class AppSearchSession implements Closeable {
Objects.requireNonNull(callback);
Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
try {
mService.removeByDocumentId(mPackageName, mDatabaseName, request.getNamespace(),
new ArrayList<>(request.getIds()), mUserId,
mService.removeByDocumentId(
mPackageName,
mDatabaseName,
request.getNamespace(),
new ArrayList<>(request.getIds()),
mUserHandle,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchBatchResultCallback.Stub() {
@Override
@@ -616,8 +620,12 @@ public final class AppSearchSession implements Closeable {
Objects.requireNonNull(callback);
Preconditions.checkState(!mIsClosed, "AppSearchSession has already been closed");
try {
mService.removeByQuery(mPackageName, mDatabaseName, queryExpression,
searchSpec.getBundle(), mUserId,
mService.removeByQuery(
mPackageName,
mDatabaseName,
queryExpression,
searchSpec.getBundle(),
mUserHandle,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override
@@ -650,7 +658,7 @@ public final class AppSearchSession implements Closeable {
mService.getStorageInfo(
mPackageName,
mDatabaseName,
mUserId,
mUserHandle,
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
@@ -678,8 +686,8 @@ public final class AppSearchSession implements Closeable {
public void close() {
if (mIsMutated && !mIsClosed) {
try {
mService.persistToDisk(mUserId,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime());
mService.persistToDisk(
mUserHandle, /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime());
mIsClosed = true;
} catch (RemoteException e) {
Log.e(TAG, "Unable to close the AppSearchSession", e);
@@ -708,7 +716,7 @@ public final class AppSearchSession implements Closeable {
schemasPackageAccessibleBundles,
request.isForceOverride(),
request.getVersion(),
mUserId,
mUserHandle,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override
@@ -796,7 +804,7 @@ public final class AppSearchSession implements Closeable {
schemasPackageAccessibleBundles,
/*forceOverride=*/ false,
request.getVersion(),
mUserId,
mUserHandle,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override
@@ -822,7 +830,7 @@ public final class AppSearchSession implements Closeable {
}
try (AppSearchMigrationHelper migrationHelper = new AppSearchMigrationHelper(
mService, mUserId, mPackageName, mDatabaseName, request.getSchemas())) {
mService, mUserHandle, mPackageName, mDatabaseName, request.getSchemas())) {
// 4. Trigger migration for all migrators.
// TODO(b/177266929) trigger migration for all types together rather than
@@ -848,7 +856,7 @@ public final class AppSearchSession implements Closeable {
schemasPackageAccessibleBundles,
/*forceOverride=*/ true,
request.getVersion(),
mUserId,
mUserHandle,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override

View File

@@ -18,12 +18,12 @@ package android.app.appsearch;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.appsearch.aidl.AppSearchResultParcel;
import android.app.appsearch.aidl.IAppSearchManager;
import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -45,24 +45,23 @@ public class GlobalSearchSession implements Closeable {
private static final String TAG = "AppSearchGlobalSearchSe";
private final String mPackageName;
@UserIdInt
private final int mUserId;
private final UserHandle mUserHandle;
private final IAppSearchManager mService;
private boolean mIsMutated = false;
private boolean mIsClosed = false;
/**
* Creates a search session for the client, defined by the {@code userId} and
* Creates a search session for the client, defined by the {@code userHandle} and
* {@code packageName}.
*/
static void createGlobalSearchSession(
@NonNull IAppSearchManager service,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@NonNull String packageName,
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<GlobalSearchSession>> callback) {
GlobalSearchSession globalSearchSession = new GlobalSearchSession(service, userId,
GlobalSearchSession globalSearchSession = new GlobalSearchSession(service, userHandle,
packageName);
globalSearchSession.initialize(executor, callback);
}
@@ -73,7 +72,8 @@ public class GlobalSearchSession implements Closeable {
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<GlobalSearchSession>> callback) {
try {
mService.initialize(mUserId,
mService.initialize(
mUserHandle,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchResultCallback.Stub() {
@Override
@@ -95,10 +95,10 @@ public class GlobalSearchSession implements Closeable {
}
}
private GlobalSearchSession(@NonNull IAppSearchManager service, @UserIdInt int userId,
private GlobalSearchSession(@NonNull IAppSearchManager service, @NonNull UserHandle userHandle,
@NonNull String packageName) {
mService = service;
mUserId = userId;
mUserHandle = userHandle;
mPackageName = packageName;
}
@@ -127,7 +127,7 @@ public class GlobalSearchSession implements Closeable {
Objects.requireNonNull(searchSpec);
Preconditions.checkState(!mIsClosed, "GlobalSearchSession has already been closed");
return new SearchResults(mService, mPackageName, /*databaseName=*/null, queryExpression,
searchSpec, mUserId);
searchSpec, mUserHandle);
}
/**
@@ -165,7 +165,7 @@ public class GlobalSearchSession implements Closeable {
request.getDocumentId(),
request.getUsageTimestampMillis(),
/*systemUsage=*/ true,
mUserId,
mUserHandle,
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
@@ -186,8 +186,8 @@ public class GlobalSearchSession implements Closeable {
public void close() {
if (mIsMutated && !mIsClosed) {
try {
mService.persistToDisk(mUserId,
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime());
mService.persistToDisk(
mUserHandle, /*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime());
mIsClosed = true;
} catch (RemoteException e) {
Log.e(TAG, "Unable to close the GlobalSearchSession", e);

View File

@@ -19,13 +19,13 @@ package android.app.appsearch;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.appsearch.aidl.AppSearchResultParcel;
import android.app.appsearch.aidl.IAppSearchManager;
import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -66,8 +66,7 @@ public class SearchResults implements Closeable {
private final SearchSpec mSearchSpec;
@UserIdInt
private final int mUserId;
private final UserHandle mUserHandle;
private long mNextPageToken;
@@ -81,13 +80,13 @@ public class SearchResults implements Closeable {
@Nullable String databaseName,
@NonNull String queryExpression,
@NonNull SearchSpec searchSpec,
@UserIdInt int userId) {
@NonNull UserHandle userHandle) {
mService = Objects.requireNonNull(service);
mPackageName = packageName;
mDatabaseName = databaseName;
mQueryExpression = Objects.requireNonNull(queryExpression);
mSearchSpec = Objects.requireNonNull(searchSpec);
mUserId = userId;
mUserHandle = Objects.requireNonNull(userHandle);
}
/**
@@ -114,18 +113,18 @@ public class SearchResults implements Closeable {
if (mDatabaseName == null) {
// Global query, there's no one package-database combination to check.
mService.globalQuery(mPackageName, mQueryExpression,
mSearchSpec.getBundle(), mUserId,
mSearchSpec.getBundle(), mUserHandle,
binderCallStartTimeMillis,
wrapCallback(executor, callback));
} else {
// Normal local query, pass in specified database.
mService.query(mPackageName, mDatabaseName, mQueryExpression,
mSearchSpec.getBundle(), mUserId,
mSearchSpec.getBundle(), mUserHandle,
binderCallStartTimeMillis,
wrapCallback(executor, callback));
}
} else {
mService.getNextPage(mNextPageToken, mUserId, wrapCallback(executor, callback));
mService.getNextPage(mNextPageToken, mUserHandle, wrapCallback(executor, callback));
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -136,7 +135,7 @@ public class SearchResults implements Closeable {
public void close() {
if (!mIsClosed) {
try {
mService.invalidateNextPageToken(mNextPageToken, mUserId);
mService.invalidateNextPageToken(mNextPageToken, mUserHandle);
mIsClosed = true;
} catch (RemoteException e) {
Log.e(TAG, "Unable to close the SearchResults", e);

View File

@@ -16,6 +16,7 @@
package android.app.appsearch.aidl;
import android.os.Bundle;
import android.os.UserHandle;
import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
import android.app.appsearch.aidl.IAppSearchResultCallback;
@@ -36,7 +37,7 @@ interface IAppSearchManager {
* @param forceOverride Whether to apply the new schema even if it is incompatible. All
* incompatible documents will be deleted.
* @param schemaVersion The overall schema version number of the request.
* @param userId Id of the calling user
* @param userHandle Handle of the calling user
* @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@link Bundle}&gt;, where the value are
@@ -50,7 +51,7 @@ interface IAppSearchManager {
in Map<String, List<Bundle>> schemasPackageAccessibleBundles,
boolean forceOverride,
in int schemaVersion,
in int userId,
in UserHandle userHandle,
in long binderCallStartTimeMillis,
in IAppSearchResultCallback callback);
@@ -59,14 +60,14 @@ interface IAppSearchManager {
*
* @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 userHandle Handle of the calling user
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@link Bundle}&gt; where the bundle is a GetSchemaResponse.
*/
void getSchema(
in String packageName,
in String databaseName,
in int userId,
in UserHandle userHandle,
in IAppSearchResultCallback callback);
/**
@@ -74,14 +75,14 @@ interface IAppSearchManager {
*
* @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 userHandle Handle of the calling user
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@link List}&lt;{@link String}&gt;&gt;.
*/
void getNamespaces(
in String packageName,
in String databaseName,
in int userId,
in UserHandle userHandle,
in IAppSearchResultCallback callback);
/**
@@ -90,7 +91,7 @@ interface IAppSearchManager {
* @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
* @param userHandle Handle of the calling user
* @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback
* If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError}
@@ -103,7 +104,7 @@ interface IAppSearchManager {
in String packageName,
in String databaseName,
in List<Bundle> documentBundles,
in int userId,
in UserHandle userHandle,
in long binderCallStartTimeMillis,
in IAppSearchBatchResultCallback callback);
@@ -116,7 +117,7 @@ interface IAppSearchManager {
* @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
* @param userHandle Handle of the calling user
* @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback
* If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError}
@@ -131,7 +132,7 @@ interface IAppSearchManager {
in String namespace,
in List<String> ids,
in Map<String, List<String>> typePropertyPaths,
in int userId,
in UserHandle userHandle,
in long binderCallStartTimeMillis,
in IAppSearchBatchResultCallback callback);
@@ -142,7 +143,7 @@ interface IAppSearchManager {
* @param databaseName The databaseName this query for.
* @param queryExpression String to search for
* @param searchSpecBundle SearchSpec bundle
* @param userId Id of the calling user
* @param userHandle Handle of the calling user
* @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback {@link AppSearchResult}&lt;{@link Bundle}&gt; of performing this
* operation.
@@ -152,7 +153,7 @@ interface IAppSearchManager {
in String databaseName,
in String queryExpression,
in Bundle searchSpecBundle,
in int userId,
in UserHandle userHandle,
in long binderCallStartTimeMillis,
in IAppSearchResultCallback callback);
@@ -163,7 +164,7 @@ interface IAppSearchManager {
* @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
* @param userHandle Handle of the calling user
* @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback {@link AppSearchResult}&lt;{@link Bundle}&gt; of performing this
* operation.
@@ -172,7 +173,7 @@ interface IAppSearchManager {
in String packageName,
in String queryExpression,
in Bundle searchSpecBundle,
in int userId,
in UserHandle userHandle,
in long binderCallStartTimeMillis,
in IAppSearchResultCallback callback);
@@ -181,20 +182,20 @@ interface IAppSearchManager {
* next-page token is invalid or all pages have been returned.
*
* @param nextPageToken The token of pre-loaded results of previously executed query.
* @param userId Id of the calling user
* @param userHandle Handle of the calling user
* @param callback {@link AppSearchResult}&lt;{@link Bundle}&gt; of performing this
* operation.
*/
void getNextPage(in long nextPageToken, in int userId, in IAppSearchResultCallback callback);
void getNextPage(in long nextPageToken, in UserHandle userHandle, in IAppSearchResultCallback callback);
/**
* Invalidates the next-page token so that no more results of the related query can be returned.
*
* @param nextPageToken The token of pre-loaded results of previously executed query to be
* Invalidated.
* @param userId Id of the calling user
* @param userHandle Handle of the calling user
*/
void invalidateNextPageToken(in long nextPageToken, in int userId);
void invalidateNextPageToken(in long nextPageToken, in UserHandle userHandle);
/**
* Searches a document based on a given specifications.
@@ -206,7 +207,7 @@ interface IAppSearchManager {
* @param fileDescriptor The ParcelFileDescriptor where documents should be written to.
* @param queryExpression String to search for.
* @param searchSpecBundle SearchSpec bundle.
* @param userId Id of the calling user.
* @param userHandle Handle of the calling user.
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@code Void}&gt;.
*/
@@ -216,7 +217,7 @@ interface IAppSearchManager {
in ParcelFileDescriptor fileDescriptor,
in String queryExpression,
in Bundle searchSpecBundle,
in int userId,
in UserHandle userHandle,
in IAppSearchResultCallback callback);
/**
@@ -225,7 +226,7 @@ interface IAppSearchManager {
* @param packageName The name of the package that owns this document.
* @param databaseName The name of the database where this document lives.
* @param fileDescriptor The ParcelFileDescriptor where documents should be read from.
* @param userId Id of the calling user.
* @param userHandle Handle of the calling user.
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@link List}&lt;{@link Bundle}&gt;&gt;, where the value are
* MigrationFailure bundles.
@@ -234,7 +235,7 @@ interface IAppSearchManager {
in String packageName,
in String databaseName,
in ParcelFileDescriptor fileDescriptor,
in int userId,
in UserHandle userHandle,
in IAppSearchResultCallback callback);
/**
@@ -255,7 +256,7 @@ interface IAppSearchManager {
* @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 userHandle Handle of the calling user
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@link Void}&gt;.
*/
@@ -266,7 +267,7 @@ interface IAppSearchManager {
in String id,
in long usageTimestampMillis,
in boolean systemUsage,
in int userId,
in UserHandle userHandle,
in IAppSearchResultCallback callback);
/**
@@ -276,7 +277,7 @@ interface IAppSearchManager {
* @param databaseName The databaseName the document is in.
* @param namespace Namespace of the document to remove.
* @param ids The IDs of the documents to delete
* @param userId Id of the calling user
* @param userHandle Handle of the calling user
* @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback
* If the call fails to start, {@link IAppSearchBatchResultCallback#onSystemError}
@@ -291,7 +292,7 @@ interface IAppSearchManager {
in String databaseName,
in String namespace,
in List<String> ids,
in int userId,
in UserHandle userHandle,
in long binderCallStartTimeMillis,
in IAppSearchBatchResultCallback callback);
@@ -302,7 +303,7 @@ interface IAppSearchManager {
* @param databaseName The databaseName this query for.
* @param queryExpression String to search for
* @param searchSpecBundle SearchSpec bundle
* @param userId Id of the calling user
* @param userHandle Handle of the calling user
* @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@link Void}&gt;.
@@ -312,7 +313,7 @@ interface IAppSearchManager {
in String databaseName,
in String queryExpression,
in Bundle searchSpecBundle,
in int userId,
in UserHandle userHandle,
in long binderCallStartTimeMillis,
in IAppSearchResultCallback callback);
@@ -321,7 +322,7 @@ interface IAppSearchManager {
*
* @param packageName The name of the package to get the storage info for.
* @param databaseName The databaseName to get the storage info for.
* @param userId Id of the calling user
* @param userHandle Handle of the calling user
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@link Bundle}&gt;, where the value is a
* {@link StorageInfo}.
@@ -329,27 +330,27 @@ interface IAppSearchManager {
void getStorageInfo(
in String packageName,
in String databaseName,
in int userId,
in UserHandle userHandle,
in IAppSearchResultCallback callback);
/**
* Persists all update/delete requests to the disk.
*
* @param userId Id of the calling user
* @param userHandle Handle of the calling user
* @param binderCallStartTimeMillis start timestamp of binder call in Millis
*/
void persistToDisk(in int userId, in long binderCallStartTimeMillis);
void persistToDisk(in UserHandle userHandle, in long binderCallStartTimeMillis);
/**
* Creates and initializes AppSearchImpl for the calling app.
*
* @param userId Id of the calling user
* @param userHandle Handle of the calling user
* @param binderCallStartTimeMillis start timestamp of binder call in Millis
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@link Void}&gt;.
*/
void initialize(
in int userId,
in UserHandle userHandle,
in long binderCallStartTimeMillis,
in IAppSearchResultCallback callback);
}

View File

@@ -21,7 +21,6 @@ import static android.os.UserHandle.USER_NULL;
import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.appsearch.AppSearchBatchResult;
import android.app.appsearch.AppSearchMigrationHelper;
@@ -45,7 +44,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageStats;
import android.os.Binder;
import android.os.Bundle;
@@ -60,7 +58,6 @@ import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalManagerRegistry;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.stats.CallStats;
@@ -91,7 +88,6 @@ public class AppSearchManagerService extends SystemService {
private static final String TAG = "AppSearchManagerService";
private final Context mContext;
private PackageManager mPackageManager;
private PackageManagerInternal mPackageManagerInternal;
private ImplInstanceManager mImplInstanceManager;
private UserManager mUserManager;
private LoggerInstanceManager mLoggerInstanceManager;
@@ -104,11 +100,11 @@ public class AppSearchManagerService extends SystemService {
Runtime.getRuntime().availableProcessors(), /*keepAliveTime*/ 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>());
// Cache of unlocked user ids so we don't have to query UserManager service each time. The
// "locked" suffix refers to the fact that access to the field should be locked; unrelated to
// the unlocked status of user ids.
@GuardedBy("mUnlockedUserIdsLocked")
private final Set<Integer> mUnlockedUserIdsLocked = new ArraySet<>();
// Cache of unlocked users so we don't have to query UserManager service each time. The "locked"
// suffix refers to the fact that access to the field should be locked; unrelated to the
// unlocked status of users.
@GuardedBy("mUnlockedUsersLocked")
private final Set<UserHandle> mUnlockedUsersLocked = new ArraySet<>();
public AppSearchManagerService(Context context) {
super(context);
@@ -119,7 +115,6 @@ public class AppSearchManagerService extends SystemService {
public void onStart() {
publishBinderService(Context.APP_SEARCH_SERVICE, new Stub());
mPackageManager = getContext().getPackageManager();
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
mImplInstanceManager = ImplInstanceManager.getInstance(mContext);
mUserManager = mContext.getSystemService(UserManager.class);
mLoggerInstanceManager = LoggerInstanceManager.getInstance();
@@ -148,6 +143,9 @@ public class AppSearchManagerService extends SystemService {
private class UserActionReceiver extends BroadcastReceiver {
@Override
public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Objects.requireNonNull(context);
Objects.requireNonNull(intent);
switch (intent.getAction()) {
case Intent.ACTION_USER_REMOVED:
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
@@ -155,7 +153,7 @@ public class AppSearchManagerService extends SystemService {
Log.e(TAG, "userId is missing in the intent: " + intent);
return;
}
handleUserRemoved(userId);
handleUserRemoved(UserHandle.of(userId));
break;
default:
Log.e(TAG, "Received unknown intent: " + intent);
@@ -170,23 +168,26 @@ public class AppSearchManagerService extends SystemService {
* "credential encrypted" system directory of each user. That directory will be auto-deleted
* when a user is removed.
*
* @param userId The multi-user userId of the user that need to be removed.
* @param userHandle The multi-user handle of the user that need to be removed.
*
* @see android.os.Environment#getDataSystemCeDirectory
*/
private void handleUserRemoved(@UserIdInt int userId) {
private void handleUserRemoved(@NonNull UserHandle userHandle) {
try {
mImplInstanceManager.removeAppSearchImplForUser(userId);
mLoggerInstanceManager.removePlatformLoggerForUser(userId);
Log.i(TAG, "Removed AppSearchImpl instance for user: " + userId);
mImplInstanceManager.removeAppSearchImplForUser(userHandle);
mLoggerInstanceManager.removePlatformLoggerForUser(userHandle);
Log.i(TAG, "Removed AppSearchImpl instance for: " + userHandle);
} catch (Throwable t) {
Log.e(TAG, "Unable to remove data for user: " + userId, t);
Log.e(TAG, "Unable to remove data for: " + userHandle, t);
}
}
private class PackageChangedReceiver extends BroadcastReceiver {
@Override
public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Objects.requireNonNull(context);
Objects.requireNonNull(intent);
switch (intent.getAction()) {
case Intent.ACTION_PACKAGE_FULLY_REMOVED:
case Intent.ACTION_PACKAGE_DATA_CLEARED:
@@ -208,19 +209,19 @@ public class AppSearchManagerService extends SystemService {
}
}
private void handlePackageRemoved(String packageName, int uid) {
int userId = UserHandle.getUserId(uid);
private void handlePackageRemoved(@NonNull String packageName, int uid) {
UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
try {
if (isUserLocked(userId)) {
if (isUserLocked(userHandle)) {
//TODO(b/186151459) clear the uninstalled package data when user is unlocked.
return;
}
if (ImplInstanceManager.getAppSearchDir(userId).exists()) {
if (ImplInstanceManager.getAppSearchDir(userHandle).exists()) {
// Only clear the package's data if AppSearch exists for this user.
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
userHandle);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
userId, logger);
userHandle, logger);
//TODO(b/145759910) clear visibility setting for package.
impl.clearPackageData(packageName);
logger.removeCachedUidForPackage(packageName);
@@ -232,38 +233,42 @@ public class AppSearchManagerService extends SystemService {
@Override
public void onUserUnlocking(@NonNull TargetUser user) {
synchronized (mUnlockedUserIdsLocked) {
mUnlockedUserIdsLocked.add(user.getUserIdentifier());
Objects.requireNonNull(user);
synchronized (mUnlockedUsersLocked) {
mUnlockedUsersLocked.add(user.getUserHandle());
}
}
@Override
public void onUserStopping(@NonNull TargetUser user) {
synchronized (mUnlockedUserIdsLocked) {
mUnlockedUserIdsLocked.remove(user.getUserIdentifier());
Objects.requireNonNull(user);
synchronized (mUnlockedUsersLocked) {
UserHandle userHandle = user.getUserHandle();
mUnlockedUsersLocked.remove(userHandle);
try {
mImplInstanceManager.closeAndRemoveAppSearchImplForUser(user.getUserIdentifier());
mImplInstanceManager.closeAndRemoveAppSearchImplForUser(userHandle);
} catch (Throwable t) {
Log.e(TAG, "Error handling user stopping.", t);
}
}
}
private void verifyUserUnlocked(int callingUserId) {
if (isUserLocked(callingUserId)) {
throw new IllegalStateException("User " + callingUserId + " is locked or not running.");
private void verifyUserUnlocked(@NonNull UserHandle callingUser) {
if (isUserLocked(callingUser)) {
throw new IllegalStateException(callingUser + " is locked or not running.");
}
}
private boolean isUserLocked(int callingUserId) {
synchronized (mUnlockedUserIdsLocked) {
private boolean isUserLocked(@NonNull UserHandle callingUser) {
synchronized (mUnlockedUsersLocked) {
// First, check the local copy.
if (mUnlockedUserIdsLocked.contains(callingUserId)) {
if (mUnlockedUsersLocked.contains(callingUser)) {
return false;
}
// If the local copy says the user is locked, check with UM for the actual state,
// since the user might just have been unlocked.
return !mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(callingUserId));
return !mUserManager.isUserUnlockingOrUnlocked(callingUser);
}
}
@@ -277,24 +282,28 @@ public class AppSearchManagerService extends SystemService {
@NonNull Map<String, List<Bundle>> schemasPackageAccessibleBundles,
boolean forceOverride,
int schemaVersion,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(schemaBundles);
Objects.requireNonNull(schemasNotDisplayedBySystem);
Objects.requireNonNull(schemasPackageAccessibleBundles);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
List<AppSearchSchema> schemas = new ArrayList<>(schemaBundles.size());
for (int i = 0; i < schemaBundles.size(); i++) {
schemas.add(new AppSearchSchema(schemaBundles.get(i)));
@@ -311,8 +320,8 @@ public class AppSearchManagerService extends SystemService {
}
schemasPackageAccessible.put(entry.getKey(), packageIdentifiers);
}
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUserId);
logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
SetSchemaResponse setSchemaResponse = impl.setSchema(
packageName,
databaseName,
@@ -356,19 +365,20 @@ public class AppSearchManagerService extends SystemService {
public void getSchema(
@NonNull String packageName,
@NonNull String databaseName,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
GetSchemaResponse response = impl.getSchema(packageName, databaseName);
invokeCallbackOnResult(
callback,
@@ -383,19 +393,20 @@ public class AppSearchManagerService extends SystemService {
public void getNamespaces(
@NonNull String packageName,
@NonNull String databaseName,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
List<String> namespaces = impl.getNamespaces(packageName, databaseName);
invokeCallbackOnResult(callback,
AppSearchResult.newSuccessfulResult(namespaces));
@@ -410,29 +421,30 @@ public class AppSearchManagerService extends SystemService {
@NonNull String packageName,
@NonNull String databaseName,
@NonNull List<Bundle> documentBundles,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchBatchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(documentBundles);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchBatchResult.Builder<String, Void> resultBuilder =
new AppSearchBatchResult.Builder<>();
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
for (int i = 0; i < documentBundles.size(); i++) {
GenericDocument document = new GenericDocument(documentBundles.get(i));
try {
@@ -488,30 +500,32 @@ public class AppSearchManagerService extends SystemService {
@NonNull String namespace,
@NonNull List<String> ids,
@NonNull Map<String, List<String>> typePropertyPaths,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchBatchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(namespace);
Objects.requireNonNull(ids);
Objects.requireNonNull(typePropertyPaths);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
new AppSearchBatchResult.Builder<>();
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
for (int i = 0; i < ids.size(); i++) {
String id = ids.get(i);
try {
@@ -568,28 +582,29 @@ public class AppSearchManagerService extends SystemService {
@NonNull String databaseName,
@NonNull String queryExpression,
@NonNull Bundle searchSpecBundle,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(queryExpression);
Objects.requireNonNull(searchSpecBundle);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
SearchResultPage searchResultPage =
impl.query(
packageName,
@@ -634,27 +649,28 @@ public class AppSearchManagerService extends SystemService {
@NonNull String packageName,
@NonNull String queryExpression,
@NonNull Bundle searchSpecBundle,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(queryExpression);
Objects.requireNonNull(searchSpecBundle);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
SearchResultPage searchResultPage =
impl.globalQuery(
queryExpression,
@@ -698,18 +714,19 @@ public class AppSearchManagerService extends SystemService {
@Override
public void getNextPage(
long nextPageToken,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
// TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally
// opened it
EXECUTOR.execute(() -> {
try {
verifyUserUnlocked(callingUserId);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
verifyUserUnlocked(callingUser);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
SearchResultPage searchResultPage = impl.getNextPage(nextPageToken);
invokeCallbackOnResult(
callback,
@@ -721,14 +738,15 @@ public class AppSearchManagerService extends SystemService {
}
@Override
public void invalidateNextPageToken(long nextPageToken, @UserIdInt int userId) {
public void invalidateNextPageToken(long nextPageToken, @NonNull UserHandle userHandle) {
Objects.requireNonNull(userHandle);
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
verifyUserUnlocked(callingUserId);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
verifyUserUnlocked(callingUser);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
impl.invalidateNextPageToken(nextPageToken);
} catch (Throwable t) {
Log.e(TAG, "Unable to invalidate the query page token", t);
@@ -743,15 +761,22 @@ public class AppSearchManagerService extends SystemService {
@NonNull ParcelFileDescriptor fileDescriptor,
@NonNull String queryExpression,
@NonNull Bundle searchSpecBundle,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(fileDescriptor);
Objects.requireNonNull(queryExpression);
Objects.requireNonNull(searchSpecBundle);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
verifyCallingPackage(callingUid, packageName);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
// we don't need to append the file. The file is always brand new.
try (DataOutputStream outputStream = new DataOutputStream(
new FileOutputStream(fileDescriptor.getFileDescriptor()))) {
@@ -783,15 +808,20 @@ public class AppSearchManagerService extends SystemService {
@NonNull String packageName,
@NonNull String databaseName,
@NonNull ParcelFileDescriptor fileDescriptor,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(fileDescriptor);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
verifyCallingPackage(callingUid, packageName);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
GenericDocument document;
ArrayList<Bundle> migrationFailureBundles = new ArrayList<>();
@@ -835,24 +865,26 @@ public class AppSearchManagerService extends SystemService {
@NonNull String documentId,
long usageTimeMillis,
boolean systemUsage,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(namespace);
Objects.requireNonNull(documentId);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
verifyUserUnlocked(callingUserId);
verifyUserUnlocked(callingUser);
if (systemUsage) {
// TODO(b/183031844): Validate that the call comes from the system
}
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
impl.reportUsage(
packageName, databaseName, namespace, documentId,
usageTimeMillis, systemUsage);
@@ -870,29 +902,31 @@ public class AppSearchManagerService extends SystemService {
@NonNull String databaseName,
@NonNull String namespace,
@NonNull List<String> ids,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchBatchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(namespace);
Objects.requireNonNull(ids);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchBatchResult.Builder<String, Void> resultBuilder =
new AppSearchBatchResult.Builder<>();
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
for (int i = 0; i < ids.size(); i++) {
String id = ids.get(i);
try {
@@ -945,7 +979,7 @@ public class AppSearchManagerService extends SystemService {
@NonNull String databaseName,
@NonNull String queryExpression,
@NonNull Bundle searchSpecBundle,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchResultCallback callback) {
// TODO(b/173532925) log CallStats once we have CALL_TYPE_REMOVE_BY_QUERY added
@@ -953,21 +987,22 @@ public class AppSearchManagerService extends SystemService {
Objects.requireNonNull(databaseName);
Objects.requireNonNull(queryExpression);
Objects.requireNonNull(searchSpecBundle);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
impl.removeByQuery(
packageName,
databaseName,
@@ -1009,19 +1044,20 @@ public class AppSearchManagerService extends SystemService {
public void getStorageInfo(
@NonNull String packageName,
@NonNull String databaseName,
@UserIdInt int userId,
@NonNull UserHandle userHandle,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(packageName);
Objects.requireNonNull(databaseName);
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
try {
verifyUserUnlocked(callingUserId);
verifyCallingPackage(callingUid, packageName);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
verifyUserUnlocked(callingUser);
verifyCallingPackage(callingUser, callingUid, packageName);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
StorageInfo storageInfo = impl.getStorageInfoForDatabase(packageName,
databaseName);
Bundle storageInfoBundle = storageInfo.getBundle();
@@ -1034,21 +1070,23 @@ public class AppSearchManagerService extends SystemService {
}
@Override
public void persistToDisk(@UserIdInt int userId,
public void persistToDisk(
@NonNull UserHandle userHandle,
@ElapsedRealtimeLong long binderCallStartTimeMillis) {
Objects.requireNonNull(userHandle);
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
AppSearchImpl impl =
mImplInstanceManager.getAppSearchImpl(callingUserId);
logger = mLoggerInstanceManager.getPlatformLogger(callingUserId);
verifyUserUnlocked(callingUser);
AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(callingUser);
logger = mLoggerInstanceManager.getPlatformLogger(callingUser);
impl.persistToDisk(PersistType.Code.FULL);
++operationSuccessCount;
} catch (Throwable t) {
@@ -1080,23 +1118,26 @@ public class AppSearchManagerService extends SystemService {
}
@Override
public void initialize(@UserIdInt int userId,
public void initialize(
@NonNull UserHandle userHandle,
@ElapsedRealtimeLong long binderCallStartTimeMillis,
@NonNull IAppSearchResultCallback callback) {
Objects.requireNonNull(userHandle);
Objects.requireNonNull(callback);
long totalLatencyStartTimeMillis = SystemClock.elapsedRealtime();
int callingUid = Binder.getCallingUid();
int callingUserId = handleIncomingUser(userId, callingUid);
UserHandle callingUser = handleIncomingUser(userHandle, callingUid);
EXECUTOR.execute(() -> {
@AppSearchResult.ResultCode int statusCode = AppSearchResult.RESULT_OK;
PlatformLogger logger = null;
int operationSuccessCount = 0;
int operationFailureCount = 0;
try {
verifyUserUnlocked(callingUserId);
logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
callingUserId);
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUserId, logger);
verifyUserUnlocked(callingUser);
logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
mContext, callingUser);
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, callingUser, logger);
++operationSuccessCount;
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
} catch (Throwable t) {
@@ -1129,16 +1170,29 @@ public class AppSearchManagerService extends SystemService {
});
}
private void verifyCallingPackage(int callingUid, @NonNull String callingPackage) {
Objects.requireNonNull(callingPackage);
if (mPackageManagerInternal.getPackageUid(
callingPackage, /*flags=*/ 0, UserHandle.getUserId(callingUid))
!= callingUid) {
private void verifyCallingPackage(
@NonNull UserHandle actualCallingUser,
int actualCallingUid,
@NonNull String claimedCallingPackage) {
Objects.requireNonNull(actualCallingUser);
Objects.requireNonNull(claimedCallingPackage);
int claimedCallingUid;
try {
Context claimedCallingContext =
mContext.createContextAsUser(actualCallingUser, /*flags=*/ 0);
claimedCallingUid = claimedCallingContext.getPackageManager().getPackageUid(
claimedCallingPackage, /*flags=*/ 0);
} catch (PackageManager.NameNotFoundException e) {
throw new SecurityException(
"Specified calling package [" + claimedCallingPackage + "] not found");
}
if (claimedCallingUid != actualCallingUid) {
throw new SecurityException(
"Specified calling package ["
+ callingPackage
+ claimedCallingPackage
+ "] does not match the calling uid "
+ callingUid);
+ actualCallingUid);
}
}
@@ -1192,19 +1246,28 @@ public class AppSearchManagerService extends SystemService {
}
}
/**
* Helper for dealing with incoming user arguments to system service calls.
*
* <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user.
*
* @return the user handle that the call should run as. Will always be a concrete user.
*/
// 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) {
@NonNull
private static UserHandle handleIncomingUser(@NonNull UserHandle userHandle, int callingUid) {
int callingPid = Binder.getCallingPid();
return ActivityManager.handleIncomingUser(
int finalUserId = ActivityManager.handleIncomingUser(
callingPid,
callingUid,
userId,
userHandle.getIdentifier(),
/*allowAll=*/ false,
/*requireFull=*/ false,
/*name=*/ null,
/*callerPackage=*/ null);
return UserHandle.of(finalUserId);
}
// TODO(b/179160886): Cache the previous storage stats.
@@ -1218,19 +1281,19 @@ public class AppSearchManagerService extends SystemService {
Objects.requireNonNull(stats);
Objects.requireNonNull(packageName);
Objects.requireNonNull(userHandle);
int userId = userHandle.getIdentifier();
try {
verifyUserUnlocked(userId);
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
userId, logger);
verifyUserUnlocked(userHandle);
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
mContext, userHandle);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(
mContext, userHandle, logger);
stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
} catch (Throwable t) {
Log.e(
TAG,
"Unable to augment storage stats for userId "
+ userId
"Unable to augment storage stats for "
+ userHandle
+ " packageName "
+ packageName,
t);
@@ -1241,17 +1304,18 @@ public class AppSearchManagerService extends SystemService {
public void augmentStatsForUid(
@NonNull PackageStats stats, int uid, boolean canCallerAccessAllStats) {
Objects.requireNonNull(stats);
int userId = UserHandle.getUserId(uid);
UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
try {
verifyUserUnlocked(userId);
verifyUserUnlocked(userHandle);
String[] packagesForUid = mPackageManager.getPackagesForUid(uid);
if (packagesForUid == null) {
return;
}
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(mContext,
userId, logger);
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
mContext, userHandle);
AppSearchImpl impl = mImplInstanceManager.getOrCreateAppSearchImpl(
mContext, userHandle, logger);
for (int i = 0; i < packagesForUid.length; i++) {
stats.dataSize +=
impl.getStorageInfoForPackage(packagesForUid[i]).getSizeBytes();
@@ -1269,24 +1333,24 @@ public class AppSearchManagerService extends SystemService {
// size of the icing dir (or use the overall StorageInfo without interpolating it).
Objects.requireNonNull(stats);
Objects.requireNonNull(userHandle);
int userId = userHandle.getIdentifier();
try {
verifyUserUnlocked(userId);
List<PackageInfo> packagesForUser =
mPackageManager.getInstalledPackagesAsUser(/*flags=*/0, userId);
verifyUserUnlocked(userHandle);
List<PackageInfo> packagesForUser = mPackageManager.getInstalledPackagesAsUser(
/*flags=*/0, userHandle.getIdentifier());
if (packagesForUser == null) {
return;
}
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(mContext,
userId);
PlatformLogger logger = mLoggerInstanceManager.getOrCreatePlatformLogger(
mContext, userHandle);
AppSearchImpl impl =
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userId, logger);
mImplInstanceManager.getOrCreateAppSearchImpl(mContext, userHandle, logger);
for (int i = 0; i < packagesForUser.size(); i++) {
String packageName = packagesForUser.get(i).packageName;
stats.dataSize += impl.getStorageInfoForPackage(packageName).getSizeBytes();
}
} catch (Throwable t) {
Log.e(TAG, "Unable to augment storage stats for user " + userId, t);
Log.e(TAG, "Unable to augment storage stats for " + userHandle, t);
}
}
}

View File

@@ -20,13 +20,12 @@ import static android.content.pm.PackageManager.MATCH_FACTORY_ONLY;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.appsearch.exceptions.AppSearchException;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Environment;
import android.os.UserHandle;
import android.util.SparseArray;
import android.util.ArrayMap;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -34,6 +33,8 @@ import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import com.android.server.appsearch.external.localstorage.AppSearchLogger;
import java.io.File;
import java.util.Map;
import java.util.Objects;
/**
* Manages the lifecycle of instances of {@link AppSearchImpl}.
@@ -46,7 +47,7 @@ public final class ImplInstanceManager {
private static ImplInstanceManager sImplInstanceManager;
@GuardedBy("mInstancesLocked")
private final SparseArray<AppSearchImpl> mInstancesLocked = new SparseArray<>();
private final Map<UserHandle, AppSearchImpl> mInstancesLocked = new ArrayMap<>();
private final String mGlobalQuerierPackage;
@@ -79,8 +80,9 @@ public final class ImplInstanceManager {
*
* <p>This folder should only be accessed after unlock.
*/
public static File getAppSearchDir(@UserIdInt int userId) {
return new File(Environment.getDataSystemCeDirectory(userId), APP_SEARCH_DIR);
public static File getAppSearchDir(@NonNull UserHandle userHandle) {
return new File(
Environment.getDataSystemCeDirectory(userHandle.getIdentifier()), APP_SEARCH_DIR);
}
/**
@@ -90,18 +92,22 @@ public final class ImplInstanceManager {
* one will be created.
*
* @param context The context
* @param userId The multi-user userId of the device user calling AppSearch
* @param userHandle The multi-user handle of the device user calling AppSearch
* @return An initialized {@link AppSearchImpl} for this user
*/
@NonNull
public AppSearchImpl getOrCreateAppSearchImpl(
@NonNull Context context, @UserIdInt int userId, @Nullable AppSearchLogger logger)
throws AppSearchException {
@NonNull Context context,
@NonNull UserHandle userHandle,
@Nullable AppSearchLogger logger) throws AppSearchException {
Objects.requireNonNull(context);
Objects.requireNonNull(userHandle);
synchronized (mInstancesLocked) {
AppSearchImpl instance = mInstancesLocked.get(userId);
AppSearchImpl instance = mInstancesLocked.get(userHandle);
if (instance == null) {
instance = createImpl(context, userId, logger);
mInstancesLocked.put(userId, instance);
instance = createImpl(context, userHandle, logger);
mInstancesLocked.put(userHandle, instance);
}
return instance;
}
@@ -116,12 +122,13 @@ public final class ImplInstanceManager {
* <p>If the user is removed, the "credential encrypted" system directory where icing lives will
* be auto-deleted. So we shouldn't worry about persist data or close the AppSearchImpl.
*
* @param userId The multi-user userId of the user that need to be removed.
* @param userHandle The multi-user user handle of the user that need to be removed.
*/
public void removeAppSearchImplForUser(@UserIdInt int userId) {
public void removeAppSearchImplForUser(@NonNull UserHandle userHandle) {
Objects.requireNonNull(userHandle);
synchronized (mInstancesLocked) {
// no need to close and persist data to disk since we are removing them now.
mInstancesLocked.remove(userId);
mInstancesLocked.remove(userHandle);
}
}
@@ -130,14 +137,15 @@ public final class ImplInstanceManager {
*
* <p>All mutation apply to this {@link AppSearchImpl} will be persisted to disk.
*
* @param userId The multi-user userId of the user that need to be removed.
* @param userHandle The multi-user user handle of the user that need to be removed.
*/
public void closeAndRemoveAppSearchImplForUser(@UserIdInt int userId) {
public void closeAndRemoveAppSearchImplForUser(@NonNull UserHandle userHandle) {
Objects.requireNonNull(userHandle);
synchronized (mInstancesLocked) {
AppSearchImpl appSearchImpl = mInstancesLocked.get(userId);
AppSearchImpl appSearchImpl = mInstancesLocked.get(userHandle);
if (appSearchImpl != null) {
appSearchImpl.close();
mInstancesLocked.remove(userId);
mInstancesLocked.remove(userHandle);
}
}
}
@@ -148,31 +156,39 @@ public final class ImplInstanceManager {
* <p>This method should only be called by an initialized SearchSession, which has been already
* created the AppSearchImpl instance for the given user.
*
* @param userId The multi-user userId of the device user calling AppSearch
* @param userHandle The multi-user handle of the device user calling AppSearch
* @return An initialized {@link AppSearchImpl} for this user
* @throws IllegalStateException if {@link AppSearchImpl} haven't created for the given user.
*/
@NonNull
public AppSearchImpl getAppSearchImpl(@UserIdInt int userId) {
public AppSearchImpl getAppSearchImpl(@NonNull UserHandle userHandle) {
Objects.requireNonNull(userHandle);
synchronized (mInstancesLocked) {
AppSearchImpl instance = mInstancesLocked.get(userId);
AppSearchImpl instance = mInstancesLocked.get(userHandle);
if (instance == null) {
// Impossible scenario, user cannot call an uninitialized SearchSession,
// getInstance should always find the instance for the given user and never try to
// create an instance for this user again.
throw new IllegalStateException(
"AppSearchImpl has never been created for this user: " + userId);
"AppSearchImpl has never been created for: " + userHandle);
}
return instance;
}
}
private AppSearchImpl createImpl(@NonNull Context context, @UserIdInt int userId,
private AppSearchImpl createImpl(
@NonNull Context context,
@NonNull UserHandle userHandle,
@Nullable AppSearchLogger logger)
throws AppSearchException {
File appSearchDir = getAppSearchDir(userId);
File appSearchDir = getAppSearchDir(userHandle);
// TODO(b/181787682): Swap AppSearchImpl and VisibilityStore to accept a UserHandle too
return AppSearchImpl.create(
appSearchDir, context, userId, mGlobalQuerierPackage, logger);
appSearchDir,
context,
userHandle.getIdentifier(),
mGlobalQuerierPackage,
/*logger=*/ null);
}
/**

View File

@@ -17,14 +17,17 @@
package com.android.server.appsearch.stats;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.content.Context;
import android.util.SparseArray;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.server.appsearch.AppSearchManagerService;
import java.util.Map;
import java.util.Objects;
/**
* Manages the lifecycle of instances of {@link PlatformLogger}.
*
@@ -40,7 +43,7 @@ public final class LoggerInstanceManager {
private static volatile LoggerInstanceManager sLoggerInstanceManager;
@GuardedBy("mInstancesLocked")
private final SparseArray<PlatformLogger> mInstancesLocked = new SparseArray<>();
private final Map<UserHandle, PlatformLogger> mInstancesLocked = new ArrayMap<>();
private LoggerInstanceManager() {
}
@@ -68,48 +71,49 @@ public final class LoggerInstanceManager {
* Gets an instance of PlatformLogger for the given user, or creates one if none exists.
*
* @param context The context
* @param userId The multi-user userId of the device user calling AppSearch
* @param userHandle The multi-user handle of the device user calling AppSearch
* @return An initialized {@link PlatformLogger} for this user
*/
@NonNull
public PlatformLogger getOrCreatePlatformLogger(
@NonNull Context context, @UserIdInt int userId) {
@NonNull Context context, @NonNull UserHandle userHandle) {
Objects.requireNonNull(userHandle);
synchronized (mInstancesLocked) {
PlatformLogger instance = mInstancesLocked.get(userId);
PlatformLogger instance = mInstancesLocked.get(userHandle);
if (instance == null) {
instance = new PlatformLogger(context, userId, new PlatformLogger.Config(
instance = new PlatformLogger(context, userHandle, new PlatformLogger.Config(
MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
DEFAULT_SAMPLING_RATIO,
// TODO(b/173532925) re-enable sampling ratios for different stats types
// once we have P/H flag manager setup in ag/13977824
/*samplingRatios=*/ new SparseIntArray()));
mInstancesLocked.put(userId, instance);
mInstancesLocked.put(userHandle, instance);
}
return instance;
}
}
/**
* Gets an instance of PlatformLogger for the given user.
*
* <p>This method should only be called by an initialized SearchSession, which has been already
* created the PlatformLogger instance for the given user.
*
* @param userId The multi-user userId of the device user calling AppSearch
* @param userHandle The multi-user handle of the device user calling AppSearch
* @return An initialized {@link PlatformLogger} for this user
* @throws IllegalStateException if {@link PlatformLogger} haven't created for the given user.
*/
@NonNull
public PlatformLogger getPlatformLogger(@UserIdInt int userId) {
public PlatformLogger getPlatformLogger(@NonNull UserHandle userHandle) {
Objects.requireNonNull(userHandle);
synchronized (mInstancesLocked) {
PlatformLogger instance = mInstancesLocked.get(userId);
PlatformLogger instance = mInstancesLocked.get(userHandle);
if (instance == null) {
// Impossible scenario, user cannot call an uninitialized SearchSession,
// getInstance should always find the instance for the given user and never try to
// create an instance for this user again.
throw new IllegalStateException(
"PlatformLogger has never been created for this user: " + userId);
"PlatformLogger has never been created for: " + userHandle);
}
return instance;
}
@@ -121,11 +125,12 @@ public final class LoggerInstanceManager {
* <p>This method should only be called if {@link AppSearchManagerService} receives an
* ACTION_USER_REMOVED, which the logger instance of given user should be removed.
*
* @param userId The multi-user userId of the user that need to be removed.
* @param userHandle The multi-user handle of the user that need to be removed.
*/
public void removePlatformLoggerForUser(@UserIdInt int userId) {
public void removePlatformLoggerForUser(@NonNull UserHandle userHandle) {
Objects.requireNonNull(userHandle);
synchronized (mInstancesLocked) {
mInstancesLocked.remove(userId);
mInstancesLocked.remove(userHandle);
}
}
}

View File

@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseIntArray;
@@ -56,8 +57,8 @@ public final class PlatformLogger implements AppSearchLogger {
// Context of the system service.
private final Context mContext;
// User ID of the caller who we're logging for.
private final int mUserId;
// User we're logging for.
private final UserHandle mUserHandle;
// Configuration for the logger
private final Config mConfig;
@@ -164,10 +165,11 @@ public final class PlatformLogger implements AppSearchLogger {
/**
* Westworld constructor
*/
public PlatformLogger(@NonNull Context context, int userId, @NonNull Config config) {
public PlatformLogger(
@NonNull Context context, @NonNull UserHandle userHandle, @NonNull Config config) {
mContext = Objects.requireNonNull(context);
mUserHandle = Objects.requireNonNull(userHandle);
mConfig = Objects.requireNonNull(config);
mUserId = userId;
}
/** Logs {@link CallStats}. */
@@ -493,7 +495,8 @@ public final class PlatformLogger implements AppSearchLogger {
// TODO(b/173532925) since VisibilityStore has the same method, we can make this a
// utility function
try {
packageUid = mContext.getPackageManager().getPackageUidAsUser(packageName, mUserId);
packageUid = mContext.getPackageManager().getPackageUidAsUser(
packageName, mUserHandle.getIdentifier());
mPackageUidCacheLocked.put(packageName, packageUid);
return packageUid;
} catch (PackageManager.NameNotFoundException e) {

View File

@@ -75,7 +75,7 @@ public class PlatformLoggerTest {
public void testCreateExtraStatsLocked_nullSamplingRatioMap_returnsDefaultSamplingRatio() {
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.USER_NULL,
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
TEST_DEFAULT_SAMPLING_RATIO,
@@ -106,7 +106,7 @@ public class PlatformLoggerTest {
samplingRatios.put(CallStats.CALL_TYPE_SEARCH, querySamplingRatio);
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.USER_NULL,
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
TEST_DEFAULT_SAMPLING_RATIO,
@@ -207,7 +207,7 @@ public class PlatformLoggerTest {
final String testPackageName = "packageName";
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.USER_NULL,
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
samplingRatio,
@@ -225,7 +225,7 @@ public class PlatformLoggerTest {
final String testPackageName = "packageName";
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.USER_NULL,
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
samplingRatio,
@@ -247,7 +247,7 @@ public class PlatformLoggerTest {
final String testPackageName = "packageName";
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.USER_NULL,
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
minTimeIntervalBetweenSamplesMillis,
samplingRatio,
@@ -269,7 +269,7 @@ public class PlatformLoggerTest {
final String testPackageName = "packageName";
PlatformLogger logger = new PlatformLogger(
ApplicationProvider.getApplicationContext(),
UserHandle.USER_NULL,
UserHandle.of(UserHandle.USER_NULL),
new PlatformLogger.Config(
minTimeIntervalBetweenSamplesMillis,
samplingRatio,
@@ -289,7 +289,7 @@ public class PlatformLoggerTest {
final int testUid = 1234;
PlatformLogger logger = new PlatformLogger(
mContext,
mContext.getUserId(),
mContext.getUser(),
new PlatformLogger.Config(
TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
TEST_DEFAULT_SAMPLING_RATIO,

View File

@@ -653,15 +653,15 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
new ArrayMap<>(1);
private Map<String, Map<String, GenericDocument>> mDocumentMap = new ArrayMap<>(1);
private String getKey(int userId, String databaseName) {
return new StringBuilder().append(userId).append("@").append(databaseName).toString();
private String getKey(UserHandle userHandle, String databaseName) {
return userHandle.getIdentifier() + "@" + databaseName;
}
@Override
public void setSchema(String packageName, String databaseName, List<Bundle> schemaBundles,
List<String> schemasNotPlatformSurfaceable,
Map<String, List<Bundle>> schemasPackageAccessibleBundles, boolean forceOverride,
int userId, int version, long binderCallStartTimeMillis,
int version, UserHandle userHandle, long binderCallStartTimeMillis,
IAppSearchResultCallback callback) throws RemoteException {
for (Map.Entry<String, List<Bundle>> entry :
schemasPackageAccessibleBundles.entrySet()) {
@@ -684,20 +684,20 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
@Override
public void getSchema(String packageName, String databaseName, int userId,
public void getSchema(String packageName, String databaseName, UserHandle userHandle,
IAppSearchResultCallback callback) throws RemoteException {
ignore(callback);
}
@Override
public void getNamespaces(String packageName, String databaseName, int userId,
public void getNamespaces(String packageName, String databaseName, UserHandle userHandle,
IAppSearchResultCallback callback) throws RemoteException {
ignore(callback);
}
@Override
public void putDocuments(String packageName, String databaseName,
List<Bundle> documentBundles, int userId, long binderCallStartTimeMillis,
List<Bundle> documentBundles, UserHandle userHandle, long binderCallStartTimeMillis,
IAppSearchBatchResultCallback callback)
throws RemoteException {
final List<GenericDocument> docs = new ArrayList<>(documentBundles.size());
@@ -706,7 +706,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
final AppSearchBatchResult.Builder<String, Void> builder =
new AppSearchBatchResult.Builder<>();
final String key = getKey(userId, databaseName);
final String key = getKey(userHandle, databaseName);
Map<String, GenericDocument> docMap = mDocumentMap.get(key);
for (GenericDocument doc : docs) {
builder.setSuccess(doc.getId(), null);
@@ -721,12 +721,12 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
@Override
public void getDocuments(String packageName, String databaseName, String namespace,
List<String> ids, Map<String, List<String>> typePropertyPaths, int userId,
long binderCallStartTimeMillis,
List<String> ids, Map<String, List<String>> typePropertyPaths,
UserHandle userHandle, long binderCallStartTimeMillis,
IAppSearchBatchResultCallback callback) throws RemoteException {
final AppSearchBatchResult.Builder<String, Bundle> builder =
new AppSearchBatchResult.Builder<>();
final String key = getKey(userId, databaseName);
final String key = getKey(userHandle, databaseName);
if (!mDocumentMap.containsKey(key)) {
for (String id : ids) {
builder.setFailure(id, AppSearchResult.RESULT_NOT_FOUND,
@@ -748,10 +748,10 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
@Override
public void query(String packageName, String databaseName, String queryExpression,
Bundle searchSpecBundle, int userId, long binderCallStartTimeMillis,
Bundle searchSpecBundle, UserHandle userHandle, long binderCallStartTimeMillis,
IAppSearchResultCallback callback)
throws RemoteException {
final String key = getKey(userId, databaseName);
final String key = getKey(userHandle, databaseName);
if (!mDocumentMap.containsKey(key)) {
final Bundle page = new Bundle();
page.putLong(SearchResultPage.NEXT_PAGE_TOKEN_FIELD, 1);
@@ -779,14 +779,14 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
@Override
public void globalQuery(String packageName, String queryExpression, Bundle searchSpecBundle,
int userId, long binderCallStartTimeMillis, IAppSearchResultCallback callback)
throws RemoteException {
UserHandle userHandle, long binderCallStartTimeMillis,
IAppSearchResultCallback callback) throws RemoteException {
ignore(callback);
}
@Override
public void getNextPage(long nextPageToken, int userId, IAppSearchResultCallback callback)
throws RemoteException {
public void getNextPage(long nextPageToken, UserHandle userHandle,
IAppSearchResultCallback callback) throws RemoteException {
final Bundle page = new Bundle();
page.putLong(SearchResultPage.NEXT_PAGE_TOKEN_FIELD, 1);
page.putParcelableArrayList(SearchResultPage.RESULTS_FIELD, new ArrayList<>());
@@ -795,28 +795,30 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
@Override
public void invalidateNextPageToken(long nextPageToken, int userId) throws RemoteException {
public void invalidateNextPageToken(long nextPageToken, UserHandle userHandle)
throws RemoteException {
}
@Override
public void writeQueryResultsToFile(String packageName, String databaseName,
ParcelFileDescriptor fileDescriptor, String queryExpression,
Bundle searchSpecBundle, int userId, IAppSearchResultCallback callback)
Bundle searchSpecBundle, UserHandle userHandle, IAppSearchResultCallback callback)
throws RemoteException {
ignore(callback);
}
@Override
public void putDocumentsFromFile(String packageName, String databaseName,
ParcelFileDescriptor fileDescriptor, int userId, IAppSearchResultCallback callback)
ParcelFileDescriptor fileDescriptor, UserHandle userHandle,
IAppSearchResultCallback callback)
throws RemoteException {
ignore(callback);
}
@Override
public void reportUsage(String packageName, String databaseName, String namespace,
String documentId, long usageTimestampMillis, boolean systemUsage, int userId,
String documentId, long usageTimestampMillis, boolean systemUsage,
UserHandle userHandle,
IAppSearchResultCallback callback)
throws RemoteException {
ignore(callback);
@@ -824,12 +826,12 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
@Override
public void removeByDocumentId(String packageName, String databaseName, String namespace,
List<String> ids, int userId, long binderCallStartTimeMillis,
List<String> ids, UserHandle userHandle, long binderCallStartTimeMillis,
IAppSearchBatchResultCallback callback)
throws RemoteException {
final AppSearchBatchResult.Builder<String, Void> builder =
new AppSearchBatchResult.Builder<>();
final String key = getKey(userId, databaseName);
final String key = getKey(userHandle, databaseName);
if (!mDocumentMap.containsKey(key)) {
for (String id : ids) {
builder.setFailure(id, AppSearchResult.RESULT_NOT_FOUND,
@@ -852,10 +854,10 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
@Override
public void removeByQuery(String packageName, String databaseName, String queryExpression,
Bundle searchSpecBundle, int userId, long binderCallStartTimeMillis,
Bundle searchSpecBundle, UserHandle userHandle, long binderCallStartTimeMillis,
IAppSearchResultCallback callback)
throws RemoteException {
final String key = getKey(userId, databaseName);
final String key = getKey(userHandle, databaseName);
if (!mDocumentMap.containsKey(key)) {
callback.onResult(
new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null)));
@@ -867,19 +869,18 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
@Override
public void getStorageInfo(String packageName, String databaseName, int userId,
public void getStorageInfo(String packageName, String databaseName, UserHandle userHandle,
IAppSearchResultCallback callback) throws RemoteException {
ignore(callback);
}
@Override
public void persistToDisk(int userId, long binderCallStartTimeMillis)
public void persistToDisk(UserHandle userHandle, long binderCallStartTimeMillis)
throws RemoteException {
}
@Override
public void initialize(int userId, long binderCallStartTimeMillis,
public void initialize(UserHandle userHandle, long binderCallStartTimeMillis,
IAppSearchResultCallback callback)
throws RemoteException {
ignore(callback);