• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app.appsearch.aidl;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.appsearch.AppSearchResult;
22 import android.app.appsearch.GetSchemaResponse;
23 import android.app.appsearch.InternalSetSchemaResponse;
24 import android.app.appsearch.ParcelableUtil;
25 import android.app.appsearch.SearchResultPage;
26 import android.app.appsearch.SearchSuggestionResult;
27 import android.app.appsearch.SetSchemaResponse.MigrationFailure;
28 import android.app.appsearch.StorageInfo;
29 import android.app.appsearch.annotation.CanIgnoreReturnValue;
30 import android.app.appsearch.safeparcel.AbstractSafeParcelable;
31 import android.app.appsearch.safeparcel.GenericDocumentParcel;
32 import android.app.appsearch.safeparcel.SafeParcelable;
33 import android.os.Parcel;
34 import android.os.Parcelable;
35 
36 import java.util.List;
37 import java.util.Objects;
38 
39 /**
40  * Parcelable wrapper around {@link AppSearchResult}.
41  *
42  * <p>{@link AppSearchResult} can contain any value, including non-parcelable values. For the
43  * specific case of sending {@link AppSearchResult} across Binder, this class wraps an {@link
44  * AppSearchResult} that contains a parcelable type and provides parcelability of the whole
45  * structure.
46  *
47  * @deprecated This class is deprecated, you should use {@link AppSearchResultParcelV2}.
48  * @param <ValueType> The type of result object for successful calls. Must be a parcelable type.
49  * @hide
50  */
51 @Deprecated
52 @SafeParcelable.Class(creator = "AppSearchResultParcelCreator", creatorIsFinal = false)
53 public final class AppSearchResultParcel<ValueType> extends AbstractSafeParcelable {
54 
55     @NonNull
56     @SuppressWarnings("rawtypes")
57     public static final Parcelable.Creator<AppSearchResultParcel> CREATOR =
58             new AppSearchResultParcelCreator() {
59                 @Override
60                 public AppSearchResultParcel createFromParcel(Parcel in) {
61                     // We pass the result we get from ParcelableUtil#readBlob to
62                     // AppSearchResultParcelCreator to decode.
63                     byte[] dataBlob = Objects.requireNonNull(ParcelableUtil.readBlob(in));
64                     // Create a parcel object to un-serialize the byte array we are reading from
65                     // Parcel.readBlob(). Parcel.WriteBlob() could take care of whether to pass
66                     // data via binder directly or Android shared memory if the data is large.
67                     Parcel unmarshallParcel = Parcel.obtain();
68                     try {
69                         unmarshallParcel.unmarshall(dataBlob, 0, dataBlob.length);
70                         unmarshallParcel.setDataPosition(0);
71                         return super.createFromParcel(unmarshallParcel);
72                     } finally {
73                         unmarshallParcel.recycle();
74                     }
75                 }
76             };
77 
78     @NonNull
79     private static final Parcelable.Creator<AppSearchResultParcel> CREATOR_WITHOUT_BLOB =
80             new AppSearchResultParcelCreator();
81 
82     @Field(id = 1)
83     @AppSearchResult.ResultCode
84     int mResultCode;
85 
86     @Field(id = 2)
87     @Nullable
88     String mErrorMessage;
89 
90     @Field(id = 3)
91     @Nullable
92     InternalSetSchemaResponse mInternalSetSchemaResponse;
93 
94     @Field(id = 4)
95     @Nullable
96     GetSchemaResponse mGetSchemaResponse;
97 
98     @Field(id = 5)
99     @Nullable
100     List<String> mStrings;
101 
102     @Field(id = 6)
103     @Nullable
104     GenericDocumentParcel mGenericDocumentParcel;
105 
106     @Field(id = 7)
107     @Nullable
108     SearchResultPage mSearchResultPage;
109 
110     @Field(id = 8)
111     @Nullable
112     List<MigrationFailure> mMigrationFailures;
113 
114     @Field(id = 9)
115     @Nullable
116     List<SearchSuggestionResult> mSearchSuggestionResults;
117 
118     @Field(id = 10)
119     @Nullable
120     StorageInfo mStorageInfo;
121 
122     @NonNull AppSearchResult<ValueType> mResultCached;
123 
124     /**
125      * Creates an AppSearchResultParcel for given value type.
126      *
127      * @param resultCode A {@link AppSearchResult} result code for {@link IAppSearchManager} API
128      *     response.
129      * @param errorMessage An error message in case of a failed response.
130      * @param internalSetSchemaResponse An {@link InternalSetSchemaResponse} type response.
131      * @param getSchemaResponse An {@link GetSchemaResponse} type response.
132      * @param strings An {@link List<String>} type response.
133      * @param genericDocumentParcel An {@link GenericDocumentParcel} type response.
134      * @param searchResultPage An {@link SearchResultPage} type response.
135      * @param migrationFailures An {@link List<MigrationFailure>} type response.
136      * @param searchSuggestionResults An {@link List<SearchSuggestionResult>} type response.
137      * @param storageInfo {@link StorageInfo} type response.
138      */
139     @Constructor
AppSearchResultParcel( @aramid = 1) @ppSearchResult.ResultCode int resultCode, @Param(id = 2) @Nullable String errorMessage, @Param(id = 3) @Nullable InternalSetSchemaResponse internalSetSchemaResponse, @Param(id = 4) @Nullable GetSchemaResponse getSchemaResponse, @Param(id = 5) @Nullable List<String> strings, @Param(id = 6) @Nullable GenericDocumentParcel genericDocumentParcel, @Param(id = 7) @Nullable SearchResultPage searchResultPage, @Param(id = 8) @Nullable List<MigrationFailure> migrationFailures, @Param(id = 9) @Nullable List<SearchSuggestionResult> searchSuggestionResults, @Param(id = 10) @Nullable StorageInfo storageInfo)140     AppSearchResultParcel(
141             @Param(id = 1) @AppSearchResult.ResultCode int resultCode,
142             @Param(id = 2) @Nullable String errorMessage,
143             @Param(id = 3) @Nullable InternalSetSchemaResponse internalSetSchemaResponse,
144             @Param(id = 4) @Nullable GetSchemaResponse getSchemaResponse,
145             @Param(id = 5) @Nullable List<String> strings,
146             @Param(id = 6) @Nullable GenericDocumentParcel genericDocumentParcel,
147             @Param(id = 7) @Nullable SearchResultPage searchResultPage,
148             @Param(id = 8) @Nullable List<MigrationFailure> migrationFailures,
149             @Param(id = 9) @Nullable List<SearchSuggestionResult> searchSuggestionResults,
150             @Param(id = 10) @Nullable StorageInfo storageInfo) {
151         mResultCode = resultCode;
152         mErrorMessage = errorMessage;
153         if (resultCode == AppSearchResult.RESULT_OK) {
154             mInternalSetSchemaResponse = internalSetSchemaResponse;
155             mGetSchemaResponse = getSchemaResponse;
156             mStrings = strings;
157             mGenericDocumentParcel = genericDocumentParcel;
158             mSearchResultPage = searchResultPage;
159             mMigrationFailures = migrationFailures;
160             mSearchSuggestionResults = searchSuggestionResults;
161             mStorageInfo = storageInfo;
162             if (mInternalSetSchemaResponse != null) {
163                 mResultCached =
164                         (AppSearchResult<ValueType>)
165                                 AppSearchResult.newSuccessfulResult(mInternalSetSchemaResponse);
166             } else if (mGetSchemaResponse != null) {
167                 mResultCached =
168                         (AppSearchResult<ValueType>)
169                                 AppSearchResult.newSuccessfulResult(mGetSchemaResponse);
170             } else if (mStrings != null) {
171                 mResultCached =
172                         (AppSearchResult<ValueType>) AppSearchResult.newSuccessfulResult(mStrings);
173             } else if (mGenericDocumentParcel != null) {
174                 mResultCached =
175                         (AppSearchResult<ValueType>)
176                                 AppSearchResult.newSuccessfulResult(mGenericDocumentParcel);
177             } else if (mSearchResultPage != null) {
178                 mResultCached =
179                         (AppSearchResult<ValueType>)
180                                 AppSearchResult.newSuccessfulResult(mSearchResultPage);
181             } else if (mMigrationFailures != null) {
182                 mResultCached =
183                         (AppSearchResult<ValueType>)
184                                 AppSearchResult.newSuccessfulResult(mMigrationFailures);
185             } else if (mSearchSuggestionResults != null) {
186                 mResultCached =
187                         (AppSearchResult<ValueType>)
188                                 AppSearchResult.newSuccessfulResult(mSearchSuggestionResults);
189             } else if (mStorageInfo != null) {
190                 mResultCached =
191                         (AppSearchResult<ValueType>)
192                                 AppSearchResult.newSuccessfulResult(mStorageInfo);
193             } else {
194                 // Default case where code is OK and value is null.
195                 mResultCached = AppSearchResult.newSuccessfulResult(null);
196             }
197         } else {
198             mResultCached = AppSearchResult.newFailedResult(mResultCode, mErrorMessage);
199         }
200     }
201 
202     /**
203      * Creates a new {@link AppSearchResultParcel} from the given result in case a successful Void
204      * response.
205      */
fromVoid()206     public static AppSearchResultParcel fromVoid() {
207         return new AppSearchResultParcel.Builder<>(AppSearchResult.RESULT_OK).build();
208     }
209 
210     /** Creates a new failed {@link AppSearchResultParcel} from result code and error message. */
211     @SuppressWarnings({"unchecked", "rawtypes"})
fromFailedResult(AppSearchResult failedResult)212     public static AppSearchResultParcel fromFailedResult(AppSearchResult failedResult) {
213         if (failedResult.isSuccess()) {
214             throw new IllegalStateException(
215                     "Creating a failed AppSearchResultParcel from a " + "successful response");
216         }
217 
218         return new AppSearchResultParcel.Builder<>(failedResult.getResultCode())
219                 .setErrorMessage(failedResult.getErrorMessage())
220                 .build();
221     }
222 
223     /**
224      * Creates a new {@link AppSearchResultParcel} from the given result in case a successful {@link
225      * InternalSetSchemaResponse}.
226      */
fromInternalSetSchemaResponse( InternalSetSchemaResponse internalSetSchemaResponse)227     public static AppSearchResultParcel<InternalSetSchemaResponse> fromInternalSetSchemaResponse(
228             InternalSetSchemaResponse internalSetSchemaResponse) {
229         return new AppSearchResultParcel.Builder<InternalSetSchemaResponse>(
230                         AppSearchResult.RESULT_OK)
231                 .setInternalSetSchemaResponse(internalSetSchemaResponse)
232                 .build();
233     }
234 
235     /**
236      * Creates a new {@link AppSearchResultParcel} from the given result in case a successful {@link
237      * GetSchemaResponse}.
238      */
fromGetSchemaResponse( GetSchemaResponse getSchemaResponse)239     public static AppSearchResultParcel<GetSchemaResponse> fromGetSchemaResponse(
240             GetSchemaResponse getSchemaResponse) {
241         return new AppSearchResultParcel.Builder<GetSchemaResponse>(AppSearchResult.RESULT_OK)
242                 .setGetSchemaResponse(getSchemaResponse)
243                 .build();
244     }
245 
246     /**
247      * Creates a new {@link AppSearchResultParcel} from the given result in case a successful {@link
248      * List}&lt;{@link String}&gt;.
249      */
fromStringList(List<String> stringList)250     public static AppSearchResultParcel<List<String>> fromStringList(List<String> stringList) {
251         return new AppSearchResultParcel.Builder<List<String>>(AppSearchResult.RESULT_OK)
252                 .setStrings(stringList)
253                 .build();
254     }
255 
256     /**
257      * Creates a new {@link AppSearchResultParcel} from the given result in case a successful {@link
258      * GenericDocumentParcel}.
259      */
fromGenericDocumentParcel( GenericDocumentParcel genericDocumentParcel)260     public static AppSearchResultParcel<GenericDocumentParcel> fromGenericDocumentParcel(
261             GenericDocumentParcel genericDocumentParcel) {
262         return new AppSearchResultParcel.Builder<GenericDocumentParcel>(AppSearchResult.RESULT_OK)
263                 .setGenericDocumentParcel(genericDocumentParcel)
264                 .build();
265     }
266 
267     /**
268      * Creates a new {@link AppSearchResultParcel} from the given result in case a successful {@link
269      * SearchResultPage}.
270      */
fromSearchResultPage( SearchResultPage searchResultPage)271     public static AppSearchResultParcel<SearchResultPage> fromSearchResultPage(
272             SearchResultPage searchResultPage) {
273         return new AppSearchResultParcel.Builder<SearchResultPage>(AppSearchResult.RESULT_OK)
274                 .setSearchResultPage(searchResultPage)
275                 .build();
276     }
277 
278     /**
279      * Creates a new {@link AppSearchResultParcel} from the given result in case a successful {@link
280      * List}&lt;{@link MigrationFailure}&gt;.
281      */
fromMigrationFailuresList( List<MigrationFailure> migrationFailureList)282     public static AppSearchResultParcel<List<MigrationFailure>> fromMigrationFailuresList(
283             List<MigrationFailure> migrationFailureList) {
284         return new AppSearchResultParcel.Builder<List<MigrationFailure>>(AppSearchResult.RESULT_OK)
285                 .setMigrationFailures(migrationFailureList)
286                 .build();
287     }
288 
289     /**
290      * Creates a new {@link AppSearchResultParcel} from the given result in case a successful {@link
291      * List}&lt;{@link SearchSuggestionResult}&gt;.
292      */
293     public static AppSearchResultParcel<List<SearchSuggestionResult>>
fromSearchSuggestionResultList( List<SearchSuggestionResult> searchSuggestionResultList)294             fromSearchSuggestionResultList(
295                     List<SearchSuggestionResult> searchSuggestionResultList) {
296         return new AppSearchResultParcel.Builder<List<SearchSuggestionResult>>(
297                         AppSearchResult.RESULT_OK)
298                 .setSearchSuggestionResults(searchSuggestionResultList)
299                 .build();
300     }
301 
302     /**
303      * Creates a new {@link AppSearchResultParcel} from the given result in case a successful {@link
304      * StorageInfo}.
305      */
fromStorageInfo(StorageInfo storageInfo)306     public static AppSearchResultParcel<StorageInfo> fromStorageInfo(StorageInfo storageInfo) {
307         return new AppSearchResultParcel.Builder<StorageInfo>(AppSearchResult.RESULT_OK)
308                 .setStorageInfo(storageInfo)
309                 .build();
310     }
311 
312 
313     @NonNull
getResult()314     public AppSearchResult<ValueType> getResult() {
315         return mResultCached;
316     }
317 
318     /** @hide */
319     @Override
writeToParcel(@onNull Parcel dest, int flags)320     public void writeToParcel(@NonNull Parcel dest, int flags) {
321         // Serializes the whole object, So that we can use Parcel.writeBlob() to send data.
322         // WriteBlob() could take care of whether to pass data via binder directly or Android shared
323         // memory if the data is large.
324         byte[] bytes;
325         Parcel data = Parcel.obtain();
326         try {
327             // We pass encoded result from AppSearchResultParcelCreator to ParcelableUtil#writeBlob.
328             directlyWriteToParcel(this, data, flags);
329             bytes = data.marshall();
330         } finally {
331             data.recycle();
332         }
333         ParcelableUtil.writeBlob(dest, bytes);
334     }
335 
directlyWriteToParcel( @onNull AppSearchResultParcel<?> result, @NonNull Parcel data, int flags)336     static void directlyWriteToParcel(
337             @NonNull AppSearchResultParcel<?> result, @NonNull Parcel data, int flags) {
338         AppSearchResultParcelCreator.writeToParcel(result, data, flags);
339     }
340 
directlyReadFromParcel(@onNull Parcel data)341     static AppSearchResultParcel<?> directlyReadFromParcel(@NonNull Parcel data) {
342         return CREATOR_WITHOUT_BLOB.createFromParcel(data);
343     }
344 
345     /**
346      * Builder for {@link AppSearchResultParcel} objects.
347      *
348      * @param <ValueType> The type of the result objects for successful results.
349      */
350     static final class Builder<ValueType> {
351 
352         @AppSearchResult.ResultCode private final int mResultCode;
353         @Nullable private String mErrorMessage;
354         @Nullable private InternalSetSchemaResponse mInternalSetSchemaResponse;
355         @Nullable private GetSchemaResponse mGetSchemaResponse;
356         @Nullable private List<String> mStrings;
357         @Nullable private GenericDocumentParcel mGenericDocumentParcel;
358         @Nullable private SearchResultPage mSearchResultPage;
359         @Nullable private List<MigrationFailure> mMigrationFailures;
360         @Nullable private List<SearchSuggestionResult> mSearchSuggestionResults;
361         @Nullable private StorageInfo mStorageInfo;
362 
363         /** Builds an {@link AppSearchResultParcel.Builder}. */
Builder(int resultCode)364         Builder(int resultCode) {
365             mResultCode = resultCode;
366         }
367 
368         @CanIgnoreReturnValue
setErrorMessage(@ullable String errorMessage)369         Builder<ValueType> setErrorMessage(@Nullable String errorMessage) {
370             mErrorMessage = errorMessage;
371             return this;
372         }
373 
374         @CanIgnoreReturnValue
setInternalSetSchemaResponse( InternalSetSchemaResponse internalSetSchemaResponse)375         Builder<ValueType> setInternalSetSchemaResponse(
376                 InternalSetSchemaResponse internalSetSchemaResponse) {
377             mInternalSetSchemaResponse = internalSetSchemaResponse;
378             return this;
379         }
380 
381         @CanIgnoreReturnValue
setGetSchemaResponse(GetSchemaResponse getSchemaResponse)382         Builder<ValueType> setGetSchemaResponse(GetSchemaResponse getSchemaResponse) {
383             mGetSchemaResponse = getSchemaResponse;
384             return this;
385         }
386 
387         @CanIgnoreReturnValue
setStrings(List<String> strings)388         Builder<ValueType> setStrings(List<String> strings) {
389             mStrings = strings;
390             return this;
391         }
392 
393         @CanIgnoreReturnValue
setGenericDocumentParcel(GenericDocumentParcel genericDocumentParcel)394         Builder<ValueType> setGenericDocumentParcel(GenericDocumentParcel genericDocumentParcel) {
395             mGenericDocumentParcel = genericDocumentParcel;
396             return this;
397         }
398 
399         @CanIgnoreReturnValue
setSearchResultPage(SearchResultPage searchResultPage)400         Builder<ValueType> setSearchResultPage(SearchResultPage searchResultPage) {
401             mSearchResultPage = searchResultPage;
402             return this;
403         }
404 
405         @CanIgnoreReturnValue
setMigrationFailures(List<MigrationFailure> migrationFailures)406         Builder<ValueType> setMigrationFailures(List<MigrationFailure> migrationFailures) {
407             mMigrationFailures = migrationFailures;
408             return this;
409         }
410 
411         @CanIgnoreReturnValue
setSearchSuggestionResults( List<SearchSuggestionResult> searchSuggestionResults)412         Builder<ValueType> setSearchSuggestionResults(
413                 List<SearchSuggestionResult> searchSuggestionResults) {
414             mSearchSuggestionResults = searchSuggestionResults;
415             return this;
416         }
417 
418         @CanIgnoreReturnValue
setStorageInfo(StorageInfo storageInfo)419         Builder<ValueType> setStorageInfo(StorageInfo storageInfo) {
420             mStorageInfo = storageInfo;
421             return this;
422         }
423 
424 
425         /**
426          * Builds an {@link AppSearchResultParcel} object from the contents of this {@link
427          * AppSearchResultParcel.Builder}.
428          */
429         @NonNull
build()430         AppSearchResultParcel<ValueType> build() {
431             return new AppSearchResultParcel<>(
432                     mResultCode,
433                     mErrorMessage,
434                     mInternalSetSchemaResponse,
435                     mGetSchemaResponse,
436                     mStrings,
437                     mGenericDocumentParcel,
438                     mSearchResultPage,
439                     mMigrationFailures,
440                     mSearchSuggestionResults,
441                     mStorageInfo);
442         }
443     }
444 }
445