Merge "Refactor how AppSearchResult and AppSearchBatchResult are parcelled." into sc-dev

This commit is contained in:
TreeHugger Robot
2021-05-11 17:06:08 +00:00
committed by Android (Google) Code Review
17 changed files with 368 additions and 210 deletions

View File

@@ -18,6 +18,7 @@ package android.app.appsearch;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.SystemService;
import android.app.appsearch.aidl.IAppSearchManager;
import android.content.Context;
import com.android.internal.util.Preconditions;

View File

@@ -17,6 +17,7 @@ package android.app.appsearch;
import android.annotation.SystemApi;
import android.app.SystemServiceRegistry;
import android.app.appsearch.aidl.IAppSearchManager;
import android.content.Context;
/**

View File

@@ -23,6 +23,9 @@ 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;
import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.app.appsearch.exceptions.AppSearchException;
import android.os.Bundle;
import android.os.Parcel;
@@ -105,8 +108,8 @@ public class AppSearchMigrationHelper implements Closeable {
mUserId,
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResult result) {
future.complete(result);
public void onResult(AppSearchResultParcel resultParcel) {
future.complete(resultParcel.getResult());
}
});
AppSearchResult<Void> result = future.get();
@@ -145,8 +148,8 @@ public class AppSearchMigrationHelper implements Closeable {
mService.putDocumentsFromFile(mPackageName, mDatabaseName, fileDescriptor, mUserId,
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResult result) {
future.complete(result);
public void onResult(AppSearchResultParcel resultParcel) {
future.complete(resultParcel.getResult());
}
});
AppSearchResult<List<Bundle>> result = future.get();

View File

@@ -19,6 +19,11 @@ 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;
import android.app.appsearch.aidl.IAppSearchManager;
import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.app.appsearch.exceptions.AppSearchException;
import android.app.appsearch.util.SchemaMigrationUtil;
import android.compat.annotation.UnsupportedAppUsage;
@@ -86,13 +91,15 @@ public final class AppSearchSession implements Closeable {
@NonNull Consumer<AppSearchResult<AppSearchSession>> callback) {
try {
mService.initialize(mUserId, new IAppSearchResultCallback.Stub() {
public void onResult(AppSearchResult result) {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> {
AppSearchResult<Void> result = resultParcel.getResult();
if (result.isSuccess()) {
callback.accept(
AppSearchResult.newSuccessfulResult(AppSearchSession.this));
} else {
callback.accept(result);
callback.accept(AppSearchResult.newFailedResult(result));
}
});
}
@@ -191,15 +198,16 @@ public final class AppSearchSession implements Closeable {
mDatabaseName,
mUserId,
new IAppSearchResultCallback.Stub() {
public void onResult(AppSearchResult result) {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> {
AppSearchResult<Bundle> result = resultParcel.getResult();
if (result.isSuccess()) {
Bundle responseBundle = (Bundle) result.getResultValue();
GetSchemaResponse response =
new GetSchemaResponse(responseBundle);
new GetSchemaResponse(result.getResultValue());
callback.accept(AppSearchResult.newSuccessfulResult(response));
} else {
callback.accept(result);
callback.accept(AppSearchResult.newFailedResult(result));
}
});
}
@@ -227,15 +235,17 @@ public final class AppSearchSession implements Closeable {
mDatabaseName,
mUserId,
new IAppSearchResultCallback.Stub() {
public void onResult(AppSearchResult result) {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> {
AppSearchResult<List<String>> result = resultParcel.getResult();
if (result.isSuccess()) {
Set<String> namespaces =
new ArraySet<>((List<String>) result.getResultValue());
new ArraySet<>(result.getResultValue());
callback.accept(
AppSearchResult.newSuccessfulResult(namespaces));
} else {
callback.accept(result);
callback.accept(AppSearchResult.newFailedResult(result));
}
});
}
@@ -280,13 +290,14 @@ public final class AppSearchSession implements Closeable {
/*binderCallStartTimeMillis=*/ SystemClock.elapsedRealtime(),
new IAppSearchBatchResultCallback.Stub() {
@Override
public void onResult(AppSearchBatchResult result) {
executor.execute(() -> callback.onResult(result));
public void onResult(AppSearchBatchResultParcel resultParcel) {
executor.execute(() -> callback.onResult(resultParcel.getResult()));
}
@Override
public void onSystemError(AppSearchResult result) {
executor.execute(() -> sendSystemErrorToCallback(result, callback));
public void onSystemError(AppSearchResultParcel resultParcel) {
executor.execute(() -> sendSystemErrorToCallback(
resultParcel.getResult(), callback));
}
});
mIsMutated = true;
@@ -341,15 +352,17 @@ public final class AppSearchSession implements Closeable {
mUserId,
new IAppSearchBatchResultCallback.Stub() {
@Override
public void onResult(AppSearchBatchResult result) {
public void onResult(AppSearchBatchResultParcel resultParcel) {
executor.execute(() -> {
AppSearchBatchResult<String, Bundle> result =
resultParcel.getResult();
AppSearchBatchResult.Builder<String, GenericDocument>
documentResultBuilder =
new AppSearchBatchResult.Builder<>();
// Translate successful results
for (Map.Entry<String, Bundle> bundleEntry :
((Map<String, Bundle>) result.getSuccesses()).entrySet()) {
result.getSuccesses().entrySet()) {
GenericDocument document;
try {
document = new GenericDocument(bundleEntry.getValue());
@@ -380,8 +393,9 @@ public final class AppSearchSession implements Closeable {
}
@Override
public void onSystemError(AppSearchResult result) {
executor.execute(() -> sendSystemErrorToCallback(result, callback));
public void onSystemError(AppSearchResultParcel result) {
executor.execute(
() -> sendSystemErrorToCallback(result.getResult(), callback));
}
});
} catch (RemoteException e) {
@@ -492,8 +506,9 @@ public final class AppSearchSession implements Closeable {
/*systemUsage=*/ false,
mUserId,
new IAppSearchResultCallback.Stub() {
public void onResult(AppSearchResult result) {
executor.execute(() -> callback.accept(result));
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> callback.accept(resultParcel.getResult()));
}
});
mIsMutated = true;
@@ -550,13 +565,14 @@ public final class AppSearchSession implements Closeable {
new ArrayList<>(request.getIds()), mUserId,
new IAppSearchBatchResultCallback.Stub() {
@Override
public void onResult(AppSearchBatchResult result) {
executor.execute(() -> callback.onResult(result));
public void onResult(AppSearchBatchResultParcel resultParcel) {
executor.execute(() -> callback.onResult(resultParcel.getResult()));
}
@Override
public void onSystemError(AppSearchResult result) {
executor.execute(() -> sendSystemErrorToCallback(result, callback));
public void onSystemError(AppSearchResultParcel resultParcel) {
executor.execute(() -> sendSystemErrorToCallback(
resultParcel.getResult(), callback));
}
});
mIsMutated = true;
@@ -598,8 +614,9 @@ public final class AppSearchSession implements Closeable {
mService.removeByQuery(mPackageName, mDatabaseName, queryExpression,
searchSpec.getBundle(), mUserId,
new IAppSearchResultCallback.Stub() {
public void onResult(AppSearchResult result) {
executor.execute(() -> callback.accept(result));
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> callback.accept(resultParcel.getResult()));
}
});
mIsMutated = true;
@@ -629,15 +646,15 @@ public final class AppSearchSession implements Closeable {
mDatabaseName,
mUserId,
new IAppSearchResultCallback.Stub() {
public void onResult(AppSearchResult result) {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> {
AppSearchResult<Bundle> result = resultParcel.getResult();
if (result.isSuccess()) {
Bundle responseBundle = (Bundle) result.getResultValue();
StorageInfo response =
new StorageInfo(responseBundle);
StorageInfo response = new StorageInfo(result.getResultValue());
callback.accept(AppSearchResult.newSuccessfulResult(response));
} else {
callback.accept(result);
callback.accept(AppSearchResult.newFailedResult(result));
}
});
}
@@ -686,13 +703,14 @@ public final class AppSearchSession implements Closeable {
request.getVersion(),
mUserId,
new IAppSearchResultCallback.Stub() {
public void onResult(AppSearchResult result) {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> {
AppSearchResult<Bundle> result = resultParcel.getResult();
if (result.isSuccess()) {
try {
SetSchemaResponse setSchemaResponse =
new SetSchemaResponse(
(Bundle) result.getResultValue());
new SetSchemaResponse(result.getResultValue());
if (!request.isForceOverride()) {
// Throw exception if there is any deleted types or
// incompatible types. That's the only case we swallowed
@@ -707,7 +725,7 @@ public final class AppSearchSession implements Closeable {
callback.accept(AppSearchResult.throwableToFailedResult(t));
}
} else {
callback.accept(result);
callback.accept(AppSearchResult.newFailedResult(result));
}
});
}
@@ -772,8 +790,9 @@ public final class AppSearchSession implements Closeable {
request.getVersion(),
mUserId,
new IAppSearchResultCallback.Stub() {
public void onResult(AppSearchResult result) {
setSchemaFuture.complete(result);
@Override
public void onResult(AppSearchResultParcel resultParcel) {
setSchemaFuture.complete(resultParcel.getResult());
}
});
AppSearchResult<Bundle> setSchemaResult = setSchemaFuture.get();
@@ -823,8 +842,8 @@ public final class AppSearchSession implements Closeable {
mUserId,
new IAppSearchResultCallback.Stub() {
@Override
public void onResult(AppSearchResult result) {
setSchema2Future.complete(result);
public void onResult(AppSearchResultParcel resultParcel) {
setSchema2Future.complete(resultParcel.getResult());
}
});
AppSearchResult<Bundle> setSchema2Result = setSchema2Future.get();

View File

@@ -16,10 +16,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.util.Log;
@@ -71,13 +73,15 @@ public class GlobalSearchSession implements Closeable {
@NonNull Consumer<AppSearchResult<GlobalSearchSession>> callback) {
try {
mService.initialize(mUserId, new IAppSearchResultCallback.Stub() {
public void onResult(AppSearchResult result) {
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> {
AppSearchResult<Void> result = resultParcel.getResult();
if (result.isSuccess()) {
callback.accept(
AppSearchResult.newSuccessfulResult(GlobalSearchSession.this));
} else {
callback.accept(result);
callback.accept(AppSearchResult.newFailedResult(result));
}
});
}
@@ -159,8 +163,9 @@ public class GlobalSearchSession implements Closeable {
/*systemUsage=*/ true,
mUserId,
new IAppSearchResultCallback.Stub() {
public void onResult(AppSearchResult result) {
executor.execute(() -> callback.accept(result));
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> callback.accept(resultParcel.getResult()));
}
});
mIsMutated = true;

View File

@@ -20,6 +20,9 @@ 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.util.Log;
@@ -139,18 +142,20 @@ public class SearchResults implements Closeable {
@NonNull @CallbackExecutor Executor executor,
@NonNull Consumer<AppSearchResult<List<SearchResult>>> callback) {
return new IAppSearchResultCallback.Stub() {
public void onResult(AppSearchResult result) {
executor.execute(() -> invokeCallback(result, callback));
@Override
public void onResult(AppSearchResultParcel resultParcel) {
executor.execute(() -> invokeCallback(resultParcel.getResult(), callback));
}
};
}
private void invokeCallback(AppSearchResult result,
private void invokeCallback(
@NonNull AppSearchResult<Bundle> searchResultPageResult,
@NonNull Consumer<AppSearchResult<List<SearchResult>>> callback) {
if (result.isSuccess()) {
if (searchResultPageResult.isSuccess()) {
try {
SearchResultPage searchResultPage =
new SearchResultPage((Bundle) result.getResultValue());
new SearchResultPage(searchResultPageResult.getResultValue());
mNextPageToken = searchResultPage.getNextPageToken();
callback.accept(AppSearchResult.newSuccessfulResult(
searchResultPage.getResults()));
@@ -158,7 +163,7 @@ public class SearchResults implements Closeable {
callback.accept(AppSearchResult.throwableToFailedResult(t));
}
} else {
callback.accept(result);
callback.accept(AppSearchResult.newFailedResult(searchResultPageResult));
}
}
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2020, The Android Open Source Project
* Copyright 2021, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.appsearch;
package android.app.appsearch.aidl;
/** {@hide} */
parcelable AppSearchResult<ValueType>;
parcelable AppSearchBatchResultParcel<ValueType>;

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.appsearch.aidl;
import android.annotation.NonNull;
import android.app.appsearch.AppSearchBatchResult;
import android.app.appsearch.AppSearchResult;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Map;
import java.util.Objects;
/**
* Parcelable wrapper around {@link AppSearchBatchResult}.
*
* <p>{@link AppSearchBatchResult} can contain any type of key and value, including non-parcelable
* values. For the specific case of sending {@link AppSearchBatchResult} across Binder, this class
* wraps an {@link AppSearchBatchResult} that has String keys and Parcelable values. It provides
* parcelability of the whole structure.
*
* @param <ValueType> The type of result object for successful calls. Must be a parcelable type.
* @hide
*/
public final class AppSearchBatchResultParcel<ValueType> implements Parcelable {
private final AppSearchBatchResult<String, ValueType> mResult;
/** Creates a new {@link AppSearchBatchResultParcel} from the given result. */
public AppSearchBatchResultParcel(@NonNull AppSearchBatchResult<String, ValueType> result) {
mResult = Objects.requireNonNull(result);
}
private AppSearchBatchResultParcel(@NonNull Parcel in) {
Bundle bundle = in.readBundle();
AppSearchBatchResult.Builder<String, ValueType> builder =
new AppSearchBatchResult.Builder<>();
for (String key : bundle.keySet()) {
AppSearchResultParcel<ValueType> resultParcel = bundle.getParcelable(key);
builder.setResult(key, resultParcel.getResult());
}
mResult = builder.build();
}
@NonNull
public AppSearchBatchResult<String, ValueType> getResult() {
return mResult;
}
/** @hide */
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
Bundle bundle = new Bundle();
for (Map.Entry<String, AppSearchResult<ValueType>> entry
: mResult.getAll().entrySet()) {
bundle.putParcelable(entry.getKey(), new AppSearchResultParcel<>(entry.getValue()));
}
dest.writeBundle(bundle);
}
/** @hide */
@Override
public int describeContents() {
return 0;
}
/** @hide */
@NonNull
public static final Creator<AppSearchBatchResultParcel<?>> CREATOR =
new Creator<AppSearchBatchResultParcel<?>>() {
@NonNull
@Override
public AppSearchBatchResultParcel<?> createFromParcel(@NonNull Parcel in) {
return new AppSearchBatchResultParcel<>(in);
}
@NonNull
@Override
public AppSearchBatchResultParcel<?>[] newArray(int size) {
return new AppSearchBatchResultParcel<?>[size];
}
};
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2020, The Android Open Source Project
* Copyright 2021, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.appsearch;
package android.app.appsearch.aidl;
/** {@hide} */
parcelable AppSearchBatchResult;
parcelable AppSearchResultParcel<ValueType>;

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.appsearch.aidl;
import android.annotation.NonNull;
import android.app.appsearch.AppSearchResult;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
/**
* Parcelable wrapper around {@link AppSearchResult}.
*
* <p>{@link AppSearchResult} can contain any value, including non-parcelable values. For the
* specific case of sending {@link AppSearchResult} across Binder, this class wraps an
* {@link AppSearchResult} that contains a parcelable type and provides parcelability of the whole
* structure.
*
* @param <ValueType> The type of result object for successful calls. Must be a parcelable type.
* @hide
*/
public final class AppSearchResultParcel<ValueType> implements Parcelable {
private final AppSearchResult<ValueType> mResult;
/** Creates a new {@link AppSearchResultParcel} from the given result. */
public AppSearchResultParcel(@NonNull AppSearchResult<ValueType> result) {
mResult = Objects.requireNonNull(result);
}
private AppSearchResultParcel(@NonNull Parcel in) {
int resultCode = in.readInt();
ValueType resultValue = (ValueType) in.readValue(/*loader=*/ null);
String errorMessage = in.readString();
if (resultCode == AppSearchResult.RESULT_OK) {
mResult = AppSearchResult.newSuccessfulResult(resultValue);
} else {
mResult = AppSearchResult.newFailedResult(resultCode, errorMessage);
}
}
@NonNull
public AppSearchResult<ValueType> getResult() {
return mResult;
}
/** @hide */
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mResult.getResultCode());
if (mResult.isSuccess()) {
dest.writeValue(mResult.getResultValue());
} else {
dest.writeValue(null);
}
dest.writeString(mResult.getErrorMessage());
}
/** @hide */
@Override
public int describeContents() {
return 0;
}
/** @hide */
@NonNull
public static final Creator<AppSearchResultParcel<?>> CREATOR =
new Creator<AppSearchResultParcel<?>>() {
@NonNull
@Override
public AppSearchResultParcel<?> createFromParcel(@NonNull Parcel in) {
return new AppSearchResultParcel<>(in);
}
@NonNull
@Override
public AppSearchResultParcel<?>[] newArray(int size) {
return new AppSearchResultParcel<?>[size];
}
};
}

View File

@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.appsearch;
package android.app.appsearch.aidl;
import android.app.appsearch.AppSearchBatchResult;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.aidl.AppSearchBatchResultParcel;
import android.app.appsearch.aidl.AppSearchResultParcel;
/** {@hide} */
oneway interface IAppSearchBatchResultCallback {
void onResult(in AppSearchBatchResult result);
void onSystemError(in AppSearchResult result);
void onResult(in AppSearchBatchResultParcel resultParcel);
void onSystemError(in AppSearchResultParcel resultParcel);
}

View File

@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.appsearch;
package android.app.appsearch.aidl;
import android.os.Bundle;
import android.app.appsearch.IAppSearchBatchResultCallback;
import android.app.appsearch.IAppSearchResultCallback;
import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.os.ParcelFileDescriptor;
/** {@hide} */
@@ -200,7 +200,7 @@ interface IAppSearchManager {
* @param searchSpecBundle SearchSpec bundle.
* @param userId Id of the calling user.
* @param callback {@link IAppSearchResultCallback#onResult} will be called with an
* {@link AppSearchResult}&lt;{@code null}&gt;.
* {@link AppSearchResult}&lt;{@code Void}&gt;.
*/
void writeQueryResultsToFile(
in String packageName,

View File

@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.appsearch;
package android.app.appsearch.aidl;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.aidl.AppSearchResultParcel;
/** {@hide} */
oneway interface IAppSearchResultCallback {
void onResult(in AppSearchResult result);
void onResult(in AppSearchResultParcel resultParcel);
}

View File

@@ -13,37 +13,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.appsearch;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
import com.android.internal.util.Preconditions;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
/**
* Provides results for AppSearch batch operations which encompass multiple documents.
*
* <p>Individual results of a batch operation are separated into two maps: one for successes and
* one for failures. For successes, {@link #getSuccesses()} will return a map of keys to
* instances of the value type. For failures, {@link #getFailures()} will return a map of keys to
* {@link AppSearchResult} objects.
* <p>Individual results of a batch operation are separated into two maps: one for successes and one
* for failures. For successes, {@link #getSuccesses()} will return a map of keys to instances of
* the value type. For failures, {@link #getFailures()} will return a map of keys to {@link
* AppSearchResult} objects.
*
* <p>Alternatively, {@link #getAll()} returns a map of keys to {@link AppSearchResult} objects for
* both successes and failures.
*
* @param <KeyType> The type of the keys for which the results will be reported.
* @param <ValueType> The type of the result objects for successful results.
* @see AppSearchSession#put
* @see AppSearchSession#getByDocumentId
* @see AppSearchSession#remove
*/
public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelable {
public final class AppSearchBatchResult<KeyType, ValueType> {
@NonNull private final Map<KeyType, ValueType> mSuccesses;
@NonNull private final Map<KeyType, AppSearchResult<ValueType>> mFailures;
@NonNull private final Map<KeyType, AppSearchResult<ValueType>> mAll;
@@ -57,27 +55,6 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl
mAll = all;
}
private AppSearchBatchResult(@NonNull Parcel in) {
mAll = Collections.unmodifiableMap(in.readHashMap(/*loader=*/ null));
Map<KeyType, ValueType> successes = new ArrayMap<>();
Map<KeyType, AppSearchResult<ValueType>> failures = new ArrayMap<>();
for (Map.Entry<KeyType, AppSearchResult<ValueType>> entry : mAll.entrySet()) {
if (entry.getValue().isSuccess()) {
successes.put(entry.getKey(), entry.getValue().getResultValue());
} else {
failures.put(entry.getKey(), entry.getValue());
}
}
mSuccesses = Collections.unmodifiableMap(successes);
mFailures = Collections.unmodifiableMap(failures);
}
/** @hide */
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeMap(mAll);
}
/** Returns {@code true} if this {@link AppSearchBatchResult} has no failures. */
public boolean isSuccess() {
return mFailures.isEmpty();
@@ -99,8 +76,8 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl
}
/**
* Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all
* failed individual results.
* Returns a {@link Map} of keys mapped to instances of {@link AppSearchResult} for all failed
* individual results.
*
* <p>The values of the {@link Map} will not be {@code null}.
*/
@@ -122,6 +99,7 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl
/**
* Asserts that this {@link AppSearchBatchResult} has no failures.
*
* @hide
*/
public void checkSuccess() {
@@ -136,33 +114,13 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl
return "{\n successes: " + mSuccesses + "\n failures: " + mFailures + "\n}";
}
/** @hide */
@Override
public int describeContents() {
return 0;
}
/** @hide */
@NonNull
public static final Creator<AppSearchBatchResult> CREATOR =
new Creator<AppSearchBatchResult>() {
@NonNull
@Override
public AppSearchBatchResult createFromParcel(@NonNull Parcel in) {
return new AppSearchBatchResult(in);
}
@NonNull
@Override
public AppSearchBatchResult[] newArray(int size) {
return new AppSearchBatchResult[size];
}
};
/**
* Builder for {@link AppSearchBatchResult} objects.
*
* <p>Once {@link #build} is called, the instance can no longer be used.
*
* @param <KeyType> The type of the keys for which the results will be reported.
* @param <ValueType> The type of the result objects for successful results.
*/
public static final class Builder<KeyType, ValueType> {
private final Map<KeyType, ValueType> mSuccesses = new ArrayMap<>();
@@ -177,7 +135,7 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl
*
* @throws IllegalStateException if the builder has already been used.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // See getSuccesses
@SuppressWarnings("MissingGetterMatchingBuilder") // See getSuccesses
@NonNull
public Builder<KeyType, ValueType> setSuccess(
@NonNull KeyType key, @Nullable ValueType result) {
@@ -193,7 +151,7 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl
*
* @throws IllegalStateException if the builder has already been used.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // See getFailures
@SuppressWarnings("MissingGetterMatchingBuilder") // See getFailures
@NonNull
public Builder<KeyType, ValueType> setFailure(
@NonNull KeyType key,
@@ -211,7 +169,7 @@ public final class AppSearchBatchResult<KeyType, ValueType> implements Parcelabl
*
* @throws IllegalStateException if the builder has already been used.
*/
@SuppressWarnings("MissingGetterMatchingBuilder") // See getAll
@SuppressWarnings("MissingGetterMatchingBuilder") // See getAll
@NonNull
public Builder<KeyType, ValueType> setResult(
@NonNull KeyType key, @NonNull AppSearchResult<ValueType> result) {

View File

@@ -13,15 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.appsearch;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.appsearch.exceptions.AppSearchException;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import com.android.internal.util.Preconditions;
@@ -36,24 +33,26 @@ import java.util.Objects;
*
* @param <ValueType> The type of result object for successful calls.
*/
public final class AppSearchResult<ValueType> implements Parcelable {
public final class AppSearchResult<ValueType> {
private static final String TAG = "AppSearchResult";
/**
* Result codes from {@link AppSearchSession} methods.
*
* @hide
*/
@IntDef(value = {
RESULT_OK,
RESULT_UNKNOWN_ERROR,
RESULT_INTERNAL_ERROR,
RESULT_INVALID_ARGUMENT,
RESULT_IO_ERROR,
RESULT_OUT_OF_SPACE,
RESULT_NOT_FOUND,
RESULT_INVALID_SCHEMA,
RESULT_SECURITY_ERROR,
})
@IntDef(
value = {
RESULT_OK,
RESULT_UNKNOWN_ERROR,
RESULT_INTERNAL_ERROR,
RESULT_INVALID_ARGUMENT,
RESULT_IO_ERROR,
RESULT_OUT_OF_SPACE,
RESULT_NOT_FOUND,
RESULT_INVALID_SCHEMA,
RESULT_SECURITY_ERROR,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ResultCode {}
@@ -109,20 +108,6 @@ public final class AppSearchResult<ValueType> implements Parcelable {
mErrorMessage = errorMessage;
}
private AppSearchResult(@NonNull Parcel in) {
mResultCode = in.readInt();
mResultValue = (ValueType) in.readValue(/*loader=*/ null);
mErrorMessage = in.readString();
}
/** @hide */
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mResultCode);
dest.writeValue(mResultValue);
dest.writeString(mErrorMessage);
}
/** Returns {@code true} if {@link #getResultCode} equals {@link AppSearchResult#RESULT_OK}. */
public boolean isSuccess() {
return getResultCode() == RESULT_OK;
@@ -154,8 +139,8 @@ public final class AppSearchResult<ValueType> implements Parcelable {
*
* <p>If {@link #isSuccess} is {@code true}, the error message is always {@code null}. The error
* message may be {@code null} even if {@link #isSuccess} is {@code false}. See the
* documentation of the particular {@link AppSearchSession} call producing this
* {@link AppSearchResult} for what is returned by {@link #getErrorMessage}.
* documentation of the particular {@link AppSearchSession} call producing this {@link
* AppSearchResult} for what is returned by {@link #getErrorMessage}.
*/
@Nullable
public String getErrorMessage() {
@@ -190,40 +175,14 @@ public final class AppSearchResult<ValueType> implements Parcelable {
return "[FAILURE(" + mResultCode + ")]: " + mErrorMessage;
}
/** @hide */
@Override
public int describeContents() {
return 0;
}
/** @hide */
@NonNull
public static final Creator<AppSearchResult> CREATOR = new Creator<AppSearchResult>() {
@NonNull
@Override
public AppSearchResult createFromParcel(@NonNull Parcel in) {
return new AppSearchResult(in);
}
@NonNull
@Override
public AppSearchResult[] newArray(int size) {
return new AppSearchResult[size];
}
};
/**
* Creates a new successful {@link AppSearchResult}.
*/
/** Creates a new successful {@link AppSearchResult}. */
@NonNull
public static <ValueType> AppSearchResult<ValueType> newSuccessfulResult(
@Nullable ValueType value) {
return new AppSearchResult<>(RESULT_OK, value, /*errorMessage=*/ null);
}
/**
* Creates a new failed {@link AppSearchResult}.
*/
/** Creates a new failed {@link AppSearchResult}. */
@NonNull
public static <ValueType> AppSearchResult<ValueType> newFailedResult(
@ResultCode int resultCode, @Nullable String errorMessage) {
@@ -238,7 +197,8 @@ public final class AppSearchResult<ValueType> implements Parcelable {
@NonNull
public static <ValueType> AppSearchResult<ValueType> newFailedResult(
@NonNull AppSearchResult<?> otherFailedResult) {
Preconditions.checkState(!otherFailedResult.isSuccess(),
Preconditions.checkState(
!otherFailedResult.isSuccess(),
"Cannot convert a success result to a failed result");
return AppSearchResult.newFailedResult(
otherFailedResult.getResultCode(), otherFailedResult.getErrorMessage());

View File

@@ -29,14 +29,16 @@ import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.GetSchemaResponse;
import android.app.appsearch.IAppSearchBatchResultCallback;
import android.app.appsearch.IAppSearchManager;
import android.app.appsearch.IAppSearchResultCallback;
import android.app.appsearch.PackageIdentifier;
import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SearchSpec;
import android.app.appsearch.SetSchemaResponse;
import android.app.appsearch.StorageInfo;
import android.app.appsearch.aidl.AppSearchBatchResultParcel;
import android.app.appsearch.aidl.AppSearchResultParcel;
import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
import android.app.appsearch.aidl.IAppSearchManager;
import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -869,7 +871,7 @@ public class AppSearchManagerService extends SystemService {
private void invokeCallbackOnResult(
IAppSearchResultCallback callback, AppSearchResult<?> result) {
try {
callback.onResult(result);
callback.onResult(new AppSearchResultParcel<>(result));
} catch (RemoteException e) {
Log.e(TAG, "Unable to send result to the callback", e);
}
@@ -877,9 +879,9 @@ public class AppSearchManagerService extends SystemService {
/** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
private void invokeCallbackOnResult(
IAppSearchBatchResultCallback callback, AppSearchBatchResult<?, ?> result) {
IAppSearchBatchResultCallback callback, AppSearchBatchResult<String, ?> result) {
try {
callback.onResult(result);
callback.onResult(new AppSearchBatchResultParcel<>(result));
} catch (RemoteException e) {
Log.e(TAG, "Unable to send result to the callback", e);
}
@@ -891,8 +893,9 @@ public class AppSearchManagerService extends SystemService {
* <p>The throwable is convert to a {@link AppSearchResult};
*/
private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
AppSearchResult<?> result = throwableToFailedResult(throwable);
try {
callback.onResult(throwableToFailedResult(throwable));
callback.onResult(new AppSearchResultParcel<>(result));
} catch (RemoteException e) {
Log.e(TAG, "Unable to send result to the callback", e);
}
@@ -905,8 +908,9 @@ public class AppSearchManagerService extends SystemService {
*/
private void invokeCallbackOnError(
@NonNull IAppSearchBatchResultCallback callback, @NonNull Throwable throwable) {
AppSearchResult<?> result = throwableToFailedResult(throwable);
try {
callback.onSystemError(throwableToFailedResult(throwable));
callback.onSystemError(new AppSearchResultParcel<>(result));
} catch (RemoteException e) {
Log.e(TAG, "Unable to send error to the callback", e);
}

View File

@@ -50,12 +50,14 @@ import android.app.appsearch.AppSearchBatchResult;
import android.app.appsearch.AppSearchManager;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.IAppSearchBatchResultCallback;
import android.app.appsearch.IAppSearchManager;
import android.app.appsearch.IAppSearchResultCallback;
import android.app.appsearch.PackageIdentifier;
import android.app.appsearch.SearchResultPage;
import android.app.appsearch.SetSchemaResponse;
import android.app.appsearch.aidl.AppSearchBatchResultParcel;
import android.app.appsearch.aidl.AppSearchResultParcel;
import android.app.appsearch.aidl.IAppSearchBatchResultCallback;
import android.app.appsearch.aidl.IAppSearchManager;
import android.app.appsearch.aidl.IAppSearchResultCallback;
import android.app.role.OnRoleHoldersChangedListener;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ActivityNotFoundException;
@@ -675,7 +677,9 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
}
final SetSchemaResponse response = new SetSchemaResponse.Builder().build();
callback.onResult(AppSearchResult.newSuccessfulResult(response.getBundle()));
callback.onResult(
new AppSearchResultParcel(
AppSearchResult.newSuccessfulResult(response.getBundle())));
}
@Override
@@ -711,7 +715,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
docMap.put(doc.getId(), doc);
}
callback.onResult(builder.build());
callback.onResult(new AppSearchBatchResultParcel<>(builder.build()));
}
@Override
@@ -737,7 +741,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
}
}
callback.onResult(builder.build());
callback.onResult(new AppSearchBatchResultParcel<>(builder.build()));
}
@Override
@@ -749,7 +753,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
final Bundle page = new Bundle();
page.putLong(SearchResultPage.NEXT_PAGE_TOKEN_FIELD, 1);
page.putParcelableArrayList(SearchResultPage.RESULTS_FIELD, new ArrayList<>());
callback.onResult(AppSearchResult.newSuccessfulResult(page));
callback.onResult(
new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(page)));
return;
}
final List<GenericDocument> documents = new ArrayList<>(mDocumentMap.get(key).values());
@@ -765,7 +770,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
resultBundles.add(resultBundle);
}
page.putParcelableArrayList(SearchResultPage.RESULTS_FIELD, resultBundles);
callback.onResult(AppSearchResult.newSuccessfulResult(page));
callback.onResult(
new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(page)));
}
@Override
@@ -780,7 +786,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
final Bundle page = new Bundle();
page.putLong(SearchResultPage.NEXT_PAGE_TOKEN_FIELD, 1);
page.putParcelableArrayList(SearchResultPage.RESULTS_FIELD, new ArrayList<>());
callback.onResult(AppSearchResult.newSuccessfulResult(page));
callback.onResult(
new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(page)));
}
@Override
@@ -835,7 +842,7 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
}
}
callback.onResult(builder.build());
callback.onResult(new AppSearchBatchResultParcel<>(builder.build()));
}
@Override
@@ -844,11 +851,13 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
throws RemoteException {
final String key = getKey(userId, databaseName);
if (!mDocumentMap.containsKey(key)) {
callback.onResult(AppSearchResult.newSuccessfulResult(null));
callback.onResult(
new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null)));
return;
}
mDocumentMap.get(key).clear();
callback.onResult(AppSearchResult.newSuccessfulResult(null));
callback.onResult(
new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null)));
}
@Override
@@ -878,7 +887,8 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
private void ignore(IAppSearchResultCallback callback) throws RemoteException {
callback.onResult(AppSearchResult.newSuccessfulResult(null));
callback.onResult(
new AppSearchResultParcel<>(AppSearchResult.newSuccessfulResult(null)));
}
}