From 2ee7641af7a30580c0743928c099df4fcfa401c4 Mon Sep 17 00:00:00 2001 From: Alexander Dorokhine Date: Tue, 4 May 2021 13:24:47 -0700 Subject: [PATCH] Refactor how AppSearchResult and AppSearchBatchResult are parcelled. Mainline modules seem to be metalava'd differently, causing the CREATOR, describeContents(), and other parcelling methods to become part of the public API. Additionally, AppSearchResult and AppSearchBatchResult were forked from Jetpack with parcelling added, and manually maintained. Additionally, the parcelling wouldn't work properly if the keys and values are not themselves parcelable, but this was not clearly documented or called out. This CL fixes these problems by creating parcelable wrappers around the upstream Jetpack AppSearchResult and AppSearchBatchResult, usable only when they contain parcelable keys and values. Bug: 146218515 Test: Presubmit Change-Id: I828a22dc6dae3e46f5d167f1a9d12627ba15d9fd --- .../app/appsearch/AppSearchManager.java | 1 + .../AppSearchManagerFrameworkInitializer.java | 1 + .../appsearch/AppSearchMigrationHelper.java | 11 ++- .../app/appsearch/AppSearchSession.java | 95 ++++++++++-------- .../app/appsearch/GlobalSearchSession.java | 15 ++- .../android/app/appsearch/SearchResults.java | 17 ++-- .../AppSearchBatchResultParcel.aidl} | 6 +- .../aidl/AppSearchBatchResultParcel.java | 97 +++++++++++++++++++ .../AppSearchResultParcel.aidl} | 6 +- .../appsearch/aidl/AppSearchResultParcel.java | 95 ++++++++++++++++++ .../IAppSearchBatchResultCallback.aidl | 10 +- .../{ => aidl}/IAppSearchManager.aidl | 8 +- .../{ => aidl}/IAppSearchResultCallback.aidl | 6 +- .../app/appsearch/AppSearchBatchResult.java | 74 +++----------- .../app/appsearch/AppSearchResult.java | 80 ++++----------- .../appsearch/AppSearchManagerService.java | 20 ++-- .../server/pm/BaseShortcutManagerTest.java | 36 ++++--- 17 files changed, 368 insertions(+), 210 deletions(-) rename apex/appsearch/framework/java/android/app/appsearch/{AppSearchResult.aidl => aidl/AppSearchBatchResultParcel.aidl} (80%) create mode 100644 apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchBatchResultParcel.java rename apex/appsearch/framework/java/android/app/appsearch/{AppSearchBatchResult.aidl => aidl/AppSearchResultParcel.aidl} (81%) create mode 100644 apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchResultParcel.java rename apex/appsearch/framework/java/android/app/appsearch/{ => aidl}/IAppSearchBatchResultCallback.aidl (70%) rename apex/appsearch/framework/java/android/app/appsearch/{ => aidl}/IAppSearchManager.aidl (98%) rename apex/appsearch/framework/java/android/app/appsearch/{ => aidl}/IAppSearchResultCallback.aidl (81%) rename apex/appsearch/framework/java/{ => external}/android/app/appsearch/AppSearchBatchResult.java (76%) rename apex/appsearch/framework/java/{ => external}/android/app/appsearch/AppSearchResult.java (82%) diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java index c4dd1a0bc4e5a..bc3c79fea9e4d 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManager.java @@ -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; diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java index ec0533e143913..7dc527aa28fbb 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchManagerFrameworkInitializer.java @@ -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; /** diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchMigrationHelper.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchMigrationHelper.java index 0089c6dc8d2e1..353051c9423b4 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchMigrationHelper.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchMigrationHelper.java @@ -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 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> result = future.get(); diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java index c112d0efc209c..5910130e6069e 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java @@ -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> callback) { try { mService.initialize(mUserId, new IAppSearchResultCallback.Stub() { - public void onResult(AppSearchResult result) { + @Override + public void onResult(AppSearchResultParcel resultParcel) { executor.execute(() -> { + AppSearchResult 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 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> result = resultParcel.getResult(); if (result.isSuccess()) { Set namespaces = - new ArraySet<>((List) 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 result = + resultParcel.getResult(); AppSearchBatchResult.Builder documentResultBuilder = new AppSearchBatchResult.Builder<>(); // Translate successful results for (Map.Entry bundleEntry : - ((Map) 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 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 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 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 setSchema2Result = setSchema2Future.get(); diff --git a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java index d49f47271055a..7d246c20251be 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java +++ b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java @@ -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> callback) { try { mService.initialize(mUserId, new IAppSearchResultCallback.Stub() { - public void onResult(AppSearchResult result) { + @Override + public void onResult(AppSearchResultParcel resultParcel) { executor.execute(() -> { + AppSearchResult 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; diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java index 531c984252881..43686724936ad 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java @@ -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>> 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 searchResultPageResult, @NonNull Consumer>> 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)); } } } diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.aidl b/apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchBatchResultParcel.aidl similarity index 80% rename from apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.aidl rename to apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchBatchResultParcel.aidl index 37ce990b97c45..89908cde582d2 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchBatchResultParcel.aidl @@ -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; \ No newline at end of file +parcelable AppSearchBatchResultParcel; diff --git a/apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchBatchResultParcel.java b/apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchBatchResultParcel.java new file mode 100644 index 0000000000000..b0cc10c2f1c16 --- /dev/null +++ b/apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchBatchResultParcel.java @@ -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}. + * + *

{@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 The type of result object for successful calls. Must be a parcelable type. + * @hide + */ +public final class AppSearchBatchResultParcel implements Parcelable { + private final AppSearchBatchResult mResult; + + /** Creates a new {@link AppSearchBatchResultParcel} from the given result. */ + public AppSearchBatchResultParcel(@NonNull AppSearchBatchResult result) { + mResult = Objects.requireNonNull(result); + } + + private AppSearchBatchResultParcel(@NonNull Parcel in) { + Bundle bundle = in.readBundle(); + AppSearchBatchResult.Builder builder = + new AppSearchBatchResult.Builder<>(); + for (String key : bundle.keySet()) { + AppSearchResultParcel resultParcel = bundle.getParcelable(key); + builder.setResult(key, resultParcel.getResult()); + } + mResult = builder.build(); + } + + @NonNull + public AppSearchBatchResult getResult() { + return mResult; + } + + /** @hide */ + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + Bundle bundle = new Bundle(); + for (Map.Entry> 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> CREATOR = + new Creator>() { + @NonNull + @Override + public AppSearchBatchResultParcel createFromParcel(@NonNull Parcel in) { + return new AppSearchBatchResultParcel<>(in); + } + + @NonNull + @Override + public AppSearchBatchResultParcel[] newArray(int size) { + return new AppSearchBatchResultParcel[size]; + } + }; +} diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.aidl b/apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchResultParcel.aidl similarity index 81% rename from apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.aidl rename to apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchResultParcel.aidl index 4686de8df268e..4e35bd5d72627 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchResultParcel.aidl @@ -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; \ No newline at end of file +parcelable AppSearchResultParcel; diff --git a/apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchResultParcel.java b/apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchResultParcel.java new file mode 100644 index 0000000000000..8b137d3bf926b --- /dev/null +++ b/apex/appsearch/framework/java/android/app/appsearch/aidl/AppSearchResultParcel.java @@ -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}. + * + *

{@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 The type of result object for successful calls. Must be a parcelable type. + * @hide + */ +public final class AppSearchResultParcel implements Parcelable { + private final AppSearchResult mResult; + + /** Creates a new {@link AppSearchResultParcel} from the given result. */ + public AppSearchResultParcel(@NonNull AppSearchResult 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 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> CREATOR = + new Creator>() { + @NonNull + @Override + public AppSearchResultParcel createFromParcel(@NonNull Parcel in) { + return new AppSearchResultParcel<>(in); + } + + @NonNull + @Override + public AppSearchResultParcel[] newArray(int size) { + return new AppSearchResultParcel[size]; + } + }; +} diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchBatchResultCallback.aidl b/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchBatchResultCallback.aidl similarity index 70% rename from apex/appsearch/framework/java/android/app/appsearch/IAppSearchBatchResultCallback.aidl rename to apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchBatchResultCallback.aidl index 64b331ea374cc..1fe19cc253e83 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchBatchResultCallback.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchBatchResultCallback.aidl @@ -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); } diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl similarity index 98% rename from apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl rename to apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl index 507bd6884cde7..6f7e82e8126c9 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchManager.aidl @@ -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}<{@code null}>. + * {@link AppSearchResult}<{@code Void}>. */ void writeQueryResultsToFile( in String packageName, diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchResultCallback.aidl b/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchResultCallback.aidl similarity index 81% rename from apex/appsearch/framework/java/android/app/appsearch/IAppSearchResultCallback.aidl rename to apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchResultCallback.aidl index 299c9957974eb..097f0d1803956 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchResultCallback.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/aidl/IAppSearchResultCallback.aidl @@ -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); } diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchBatchResult.java similarity index 76% rename from apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java rename to apex/appsearch/framework/java/external/android/app/appsearch/AppSearchBatchResult.java index 9ae0d622dfae1..aca0fc07eb65c 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchBatchResult.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchBatchResult.java @@ -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. * - *

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. + *

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. * *

Alternatively, {@link #getAll()} returns a map of keys to {@link AppSearchResult} objects for * both successes and failures. * + * @param The type of the keys for which the results will be reported. + * @param The type of the result objects for successful results. * @see AppSearchSession#put * @see AppSearchSession#getByDocumentId * @see AppSearchSession#remove */ -public final class AppSearchBatchResult implements Parcelable { +public final class AppSearchBatchResult { @NonNull private final Map mSuccesses; @NonNull private final Map> mFailures; @NonNull private final Map> mAll; @@ -57,27 +55,6 @@ public final class AppSearchBatchResult implements Parcelabl mAll = all; } - private AppSearchBatchResult(@NonNull Parcel in) { - mAll = Collections.unmodifiableMap(in.readHashMap(/*loader=*/ null)); - Map successes = new ArrayMap<>(); - Map> failures = new ArrayMap<>(); - for (Map.Entry> 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 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. * *

The values of the {@link Map} will not be {@code null}. */ @@ -122,6 +99,7 @@ public final class AppSearchBatchResult implements Parcelabl /** * Asserts that this {@link AppSearchBatchResult} has no failures. + * * @hide */ public void checkSuccess() { @@ -136,33 +114,13 @@ public final class AppSearchBatchResult implements Parcelabl return "{\n successes: " + mSuccesses + "\n failures: " + mFailures + "\n}"; } - /** @hide */ - @Override - public int describeContents() { - return 0; - } - - /** @hide */ - @NonNull - public static final Creator CREATOR = - new Creator() { - @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. * *

Once {@link #build} is called, the instance can no longer be used. + * + * @param The type of the keys for which the results will be reported. + * @param The type of the result objects for successful results. */ public static final class Builder { private final Map mSuccesses = new ArrayMap<>(); @@ -177,7 +135,7 @@ public final class AppSearchBatchResult implements Parcelabl * * @throws IllegalStateException if the builder has already been used. */ - @SuppressWarnings("MissingGetterMatchingBuilder") // See getSuccesses + @SuppressWarnings("MissingGetterMatchingBuilder") // See getSuccesses @NonNull public Builder setSuccess( @NonNull KeyType key, @Nullable ValueType result) { @@ -193,7 +151,7 @@ public final class AppSearchBatchResult implements Parcelabl * * @throws IllegalStateException if the builder has already been used. */ - @SuppressWarnings("MissingGetterMatchingBuilder") // See getFailures + @SuppressWarnings("MissingGetterMatchingBuilder") // See getFailures @NonNull public Builder setFailure( @NonNull KeyType key, @@ -211,7 +169,7 @@ public final class AppSearchBatchResult implements Parcelabl * * @throws IllegalStateException if the builder has already been used. */ - @SuppressWarnings("MissingGetterMatchingBuilder") // See getAll + @SuppressWarnings("MissingGetterMatchingBuilder") // See getAll @NonNull public Builder setResult( @NonNull KeyType key, @NonNull AppSearchResult result) { diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.java b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchResult.java similarity index 82% rename from apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.java rename to apex/appsearch/framework/java/external/android/app/appsearch/AppSearchResult.java index b06e21516cac3..30c98b0c88662 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchResult.java +++ b/apex/appsearch/framework/java/external/android/app/appsearch/AppSearchResult.java @@ -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 The type of result object for successful calls. */ -public final class AppSearchResult implements Parcelable { +public final class AppSearchResult { 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 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 implements Parcelable { * *

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 implements Parcelable { return "[FAILURE(" + mResultCode + ")]: " + mErrorMessage; } - /** @hide */ - @Override - public int describeContents() { - return 0; - } - - /** @hide */ - @NonNull - public static final Creator CREATOR = new Creator() { - @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 AppSearchResult 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 AppSearchResult newFailedResult( @ResultCode int resultCode, @Nullable String errorMessage) { @@ -238,7 +197,8 @@ public final class AppSearchResult implements Parcelable { @NonNull public static AppSearchResult 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()); diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java index a4188a2733b86..0f42d8583e836 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -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 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 { *

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); } diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java index 358120664cea0..4a09cf8b6c268 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -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 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))); } }