• 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.AppSearchBatchResult;
22 import android.app.appsearch.AppSearchResult;
23 import android.app.appsearch.ParcelableUtil;
24 import android.app.appsearch.safeparcel.AbstractSafeParcelable;
25 import android.app.appsearch.safeparcel.GenericDocumentParcel;
26 import android.app.appsearch.safeparcel.SafeParcelable;
27 import android.os.Bundle;
28 import android.os.Parcel;
29 import android.os.Parcelable;
30 
31 import java.util.Map;
32 import java.util.Objects;
33 
34 /**
35  * Parcelable wrapper around {@link AppSearchBatchResult}.
36  *
37  * <p>{@link AppSearchBatchResult} can contain any type of key and value, including non-parcelable
38  * values. For the specific case of sending {@link AppSearchBatchResult} across Binder, this class
39  * wraps an {@link AppSearchBatchResult} that has String keys and Parcelable values. It provides
40  * parcelability of the whole structure.
41  *
42  * @deprecated This class is deprecated, you should use {@link AppSearchBatchResultParcelV2}.
43  * @param <ValueType> The type of result object for successful calls. Must be a parcelable type.
44  * @hide
45  */
46 @Deprecated
47 @SafeParcelable.Class(creator = "AppSearchBatchResultParcelCreator", creatorIsFinal = false)
48 public final class AppSearchBatchResultParcel<ValueType> extends AbstractSafeParcelable {
49 
50     @NonNull
51     @SuppressWarnings("rawtypes")
52     public static final Parcelable.Creator<AppSearchBatchResultParcel> CREATOR =
53             new AppSearchBatchResultParcelCreator() {
54                 @Override
55                 public AppSearchBatchResultParcel createFromParcel(Parcel in) {
56                     byte[] dataBlob = Objects.requireNonNull(ParcelableUtil.readBlob(in));
57                     Parcel unmarshallParcel = Parcel.obtain();
58                     try {
59                         unmarshallParcel.unmarshall(dataBlob, 0, dataBlob.length);
60                         unmarshallParcel.setDataPosition(0);
61                         int size = unmarshallParcel.dataSize();
62                         Bundle inputBundle = new Bundle();
63                         while (unmarshallParcel.dataPosition() < size) {
64                             String key = Objects.requireNonNull(unmarshallParcel.readString());
65                             AppSearchResultParcel appSearchResultParcel =
66                                     AppSearchResultParcel.directlyReadFromParcel(unmarshallParcel);
67                             inputBundle.putParcelable(key, appSearchResultParcel);
68                         }
69                         return new AppSearchBatchResultParcel(inputBundle);
70                     } finally {
71                         unmarshallParcel.recycle();
72                     }
73                 }
74             };
75 
76     // Map between String Key and AppSearchResultParcel Value.
77     @Field(id = 1)
78     @NonNull
79     final Bundle mAppSearchResultBundle;
80 
81     @Nullable private AppSearchBatchResult<String, ValueType> mResultCached;
82 
83     @Constructor
AppSearchBatchResultParcel(@aramid = 1) Bundle appSearchResultBundle)84     AppSearchBatchResultParcel(@Param(id = 1) Bundle appSearchResultBundle) {
85         mAppSearchResultBundle = appSearchResultBundle;
86     }
87 
88     /**
89      * Creates a new {@link AppSearchBatchResultParcel} from the given {@link GenericDocumentParcel}
90      * results.
91      */
92     @SuppressWarnings("unchecked")
93     public static AppSearchBatchResultParcel<GenericDocumentParcel>
fromStringToGenericDocumentParcel( @onNull AppSearchBatchResult<String, GenericDocumentParcel> result)94             fromStringToGenericDocumentParcel(
95                     @NonNull AppSearchBatchResult<String, GenericDocumentParcel> result) {
96         Bundle appSearchResultBundle = new Bundle();
97         for (Map.Entry<String, AppSearchResult<GenericDocumentParcel>> entry :
98                 result.getAll().entrySet()) {
99             AppSearchResultParcel<GenericDocumentParcel> appSearchResultParcel;
100             // Create result from value in success case and errorMessage in
101             // failure case.
102             if (entry.getValue().isSuccess()) {
103                 GenericDocumentParcel genericDocumentParcel =
104                         Objects.requireNonNull(entry.getValue().getResultValue());
105                 appSearchResultParcel =
106                         AppSearchResultParcel.fromGenericDocumentParcel(genericDocumentParcel);
107             } else {
108                 appSearchResultParcel = AppSearchResultParcel.fromFailedResult(entry.getValue());
109             }
110             appSearchResultBundle.putParcelable(entry.getKey(), appSearchResultParcel);
111         }
112         return new AppSearchBatchResultParcel<>(appSearchResultBundle);
113     }
114 
115     /** Creates a new {@link AppSearchBatchResultParcel} from the given {@link Void} results. */
116     @SuppressWarnings("unchecked")
fromStringToVoid( @onNull AppSearchBatchResult<String, Void> result)117     public static AppSearchBatchResultParcel<Void> fromStringToVoid(
118             @NonNull AppSearchBatchResult<String, Void> result) {
119         Bundle appSearchResultBundle = new Bundle();
120         for (Map.Entry<String, AppSearchResult<Void>> entry : result.getAll().entrySet()) {
121             AppSearchResultParcel<Void> appSearchResultParcel;
122             // Create result from value in success case and errorMessage in
123             // failure case.
124             if (entry.getValue().isSuccess()) {
125                 appSearchResultParcel = AppSearchResultParcel.fromVoid();
126             } else {
127                 appSearchResultParcel = AppSearchResultParcel.fromFailedResult(entry.getValue());
128             }
129             appSearchResultBundle.putParcelable(entry.getKey(), appSearchResultParcel);
130         }
131         return new AppSearchBatchResultParcel<>(appSearchResultBundle);
132     }
133 
134     @NonNull
135     @SuppressWarnings("unchecked")
getResult()136     public AppSearchBatchResult<String, ValueType> getResult() {
137         if (mResultCached == null) {
138             AppSearchBatchResult.Builder<String, ValueType> builder =
139                     new AppSearchBatchResult.Builder<>();
140             for (String key : mAppSearchResultBundle.keySet()) {
141                 builder.setResult(
142                         key,
143                         mAppSearchResultBundle
144                                 .getParcelable(key, AppSearchResultParcel.class)
145                                 .getResult());
146             }
147             mResultCached = builder.build();
148         }
149         return mResultCached;
150     }
151 
152     /** @hide */
153     @Override
154     @SuppressWarnings("unchecked")
writeToParcel(@onNull Parcel dest, int flags)155     public void writeToParcel(@NonNull Parcel dest, int flags) {
156         byte[] bytes;
157         // Create a parcel object to serialize results. So that we can use Parcel.writeBlob() to
158         // send data. WriteBlob() could take care of whether to pass data via binder directly or
159         // Android shared memory if the data is large.
160         Parcel data = Parcel.obtain();
161         try {
162             for (String key : mAppSearchResultBundle.keySet()) {
163                 data.writeString(key);
164                 AppSearchResultParcel<ValueType> appSearchResultParcel =
165                         mAppSearchResultBundle.getParcelable(key, AppSearchResultParcel.class);
166                 AppSearchResultParcel.directlyWriteToParcel(appSearchResultParcel, data, flags);
167             }
168             bytes = data.marshall();
169         } finally {
170             data.recycle();
171         }
172         ParcelableUtil.writeBlob(dest, bytes);
173     }
174 }
175