1 /*
2  * Copyright (C) 2022 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.app.appsearch.GenericDocument;
21 import android.app.appsearch.ParcelableUtil;
22 import android.app.appsearch.safeparcel.AbstractSafeParcelable;
23 import android.app.appsearch.safeparcel.GenericDocumentParcel;
24 import android.app.appsearch.safeparcel.SafeParcelable;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 
28 import java.util.List;
29 import java.util.Objects;
30 
31 /**
32  * The Parcelable object contains a List of {@link GenericDocument}.
33  *
34  * <p>This class will batch a list of {@link GenericDocument}. If the number of documents is too
35  * large for a transaction, they will be put to Android Shared Memory.
36  *
37  * @see Parcel#writeBlob(byte[])
38  * @hide
39  */
40 @SafeParcelable.Class(creator = "DocumentsParcelCreator", creatorIsFinal = false)
41 public final class DocumentsParcel extends AbstractSafeParcelable {
42     public static final Parcelable.Creator<DocumentsParcel> CREATOR =
43             new DocumentsParcelCreator() {
44                 @Override
45                 public DocumentsParcel createFromParcel(Parcel in) {
46                     byte[] dataBlob = Objects.requireNonNull(ParcelableUtil.readBlob(in));
47                     // Create a parcel object to un-serialize the byte array we are reading from
48                     // Parcel.readBlob(). Parcel.WriteBlob() could take care of whether to pass data
49                     // via
50                     // binder directly or Android shared memory if the data is large.
51                     Parcel unmarshallParcel = Parcel.obtain();
52                     try {
53                         unmarshallParcel.unmarshall(dataBlob, 0, dataBlob.length);
54                         unmarshallParcel.setDataPosition(0);
55                         return super.createFromParcel(unmarshallParcel);
56                     } finally {
57                         unmarshallParcel.recycle();
58                     }
59                 }
60             };
61 
62     @Field(id = 1, getter = "getDocumentParcels")
63     final List<GenericDocumentParcel> mDocumentParcels;
64 
65     @Field(id = 2, getter = "getTakenActionGenericDocumentParcels")
66     final List<GenericDocumentParcel> mTakenActionGenericDocumentParcels;
67 
68     @Constructor
DocumentsParcel( @aramid = 1) List<GenericDocumentParcel> documentParcels, @Param(id = 2) List<GenericDocumentParcel> takenActionGenericDocumentParcels)69     public DocumentsParcel(
70             @Param(id = 1) List<GenericDocumentParcel> documentParcels,
71             @Param(id = 2) List<GenericDocumentParcel> takenActionGenericDocumentParcels) {
72         mDocumentParcels = documentParcels;
73         mTakenActionGenericDocumentParcels = takenActionGenericDocumentParcels;
74     }
75 
76     @Override
writeToParcel(Parcel dest, int flags)77     public void writeToParcel(Parcel dest, int flags) {
78         ParcelableUtil.writeBlob(dest, serializeToByteArray(flags));
79     }
80 
81     /**
82      * Serializes the provided list of documents, So that we can use Parcel.writeBlob() to send
83      * data.
84      *
85      * <p>WriteBlob() will take care of whether to pass data via binder directly or Android shared
86      * memory if the data is large.
87      */
88     @NonNull
serializeToByteArray(int flags)89     private byte[] serializeToByteArray(int flags) {
90         byte[] bytes;
91         Parcel data = Parcel.obtain();
92         try {
93             DocumentsParcelCreator.writeToParcel(this, data, flags);
94             bytes = data.marshall();
95         } finally {
96             data.recycle();
97         }
98         return bytes;
99     }
100 
101     /** Returns the List of {@link GenericDocument} of this object. */
102     @NonNull
getDocumentParcels()103     public List<GenericDocumentParcel> getDocumentParcels() {
104         return mDocumentParcels;
105     }
106 
107     /** Returns the List of TakenActions as {@link GenericDocument}. */
108     @NonNull
getTakenActionGenericDocumentParcels()109     public List<GenericDocumentParcel> getTakenActionGenericDocumentParcels() {
110         return mTakenActionGenericDocumentParcels;
111     }
112 
113     /** Returns sum of the counts of Documents and TakenActionGenericDocuments. */
getTotalDocumentCount()114     public int getTotalDocumentCount() {
115         return mDocumentParcels.size() + mTakenActionGenericDocumentParcels.size();
116     }
117 }
118