• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 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.safeparcel;
18 
19 import android.annotation.SuppressLint;
20 import android.app.appsearch.AppSearchBlobHandle;
21 import android.app.appsearch.EmbeddingVector;
22 import android.app.appsearch.annotation.CanIgnoreReturnValue;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 import org.jspecify.annotations.NonNull;
27 import org.jspecify.annotations.Nullable;
28 
29 import java.util.Arrays;
30 import java.util.Objects;
31 
32 /**
33  * A {@link SafeParcelable} to hold the value of a property in {@code GenericDocument#mProperties}.
34  *
35  * <p>This resembles PropertyProto in IcingLib.
36  *
37  * @hide
38  */
39 @SafeParcelable.Class(creator = "PropertyParcelCreator")
40 // This won't be used to send data over binder, and we have to use Parcelable for code sync purpose.
41 @SuppressLint("BanParcelableUsage")
42 public final class PropertyParcel extends AbstractSafeParcelable implements Parcelable {
43     public static final Parcelable.@NonNull Creator<PropertyParcel> CREATOR =
44             new PropertyParcelCreator();
45 
46     @Field(id = 1, getter = "getPropertyName")
47     private final @NonNull String mPropertyName;
48 
49     @Field(id = 2, getter = "getStringValues")
50     private final String @Nullable [] mStringValues;
51 
52     @Field(id = 3, getter = "getLongValues")
53     private final long @Nullable [] mLongValues;
54 
55     @Field(id = 4, getter = "getDoubleValues")
56     private final double @Nullable [] mDoubleValues;
57 
58     @Field(id = 5, getter = "getBooleanValues")
59     private final boolean @Nullable [] mBooleanValues;
60 
61     @Field(id = 6, getter = "getBytesValues")
62     private final byte @Nullable [][] mBytesValues;
63 
64     @Field(id = 7, getter = "getDocumentValues")
65     private final GenericDocumentParcel @Nullable [] mDocumentValues;
66 
67     @Field(id = 8, getter = "getEmbeddingValues")
68     private final EmbeddingVector @Nullable [] mEmbeddingValues;
69 
70     @Field(id = 9, getter = "getBlobHandleValues")
71     private final AppSearchBlobHandle @Nullable [] mBlobHandleValues;
72 
73     private @Nullable Integer mHashCode;
74 
75     @Constructor
PropertyParcel( @aramid = 1) @onNull String propertyName, @Param(id = 2) String @Nullable [] stringValues, @Param(id = 3) long @Nullable [] longValues, @Param(id = 4) double @Nullable [] doubleValues, @Param(id = 5) boolean @Nullable [] booleanValues, @Param(id = 6) byte @Nullable [][] bytesValues, @Param(id = 7) GenericDocumentParcel @Nullable [] documentValues, @Param(id = 8) EmbeddingVector @Nullable [] embeddingValues, @Param(id = 9) AppSearchBlobHandle @Nullable [] blobHandleValues)76     PropertyParcel(
77             @Param(id = 1) @NonNull String propertyName,
78             @Param(id = 2) String @Nullable [] stringValues,
79             @Param(id = 3) long @Nullable [] longValues,
80             @Param(id = 4) double @Nullable [] doubleValues,
81             @Param(id = 5) boolean @Nullable [] booleanValues,
82             @Param(id = 6) byte @Nullable [][] bytesValues,
83             @Param(id = 7) GenericDocumentParcel @Nullable [] documentValues,
84             @Param(id = 8) EmbeddingVector @Nullable [] embeddingValues,
85             @Param(id = 9) AppSearchBlobHandle @Nullable [] blobHandleValues) {
86         mPropertyName = Objects.requireNonNull(propertyName);
87         mStringValues = stringValues;
88         mLongValues = longValues;
89         mDoubleValues = doubleValues;
90         mBooleanValues = booleanValues;
91         mBytesValues = bytesValues;
92         mDocumentValues = documentValues;
93         mEmbeddingValues = embeddingValues;
94         mBlobHandleValues = blobHandleValues;
95         checkOnlyOneArrayCanBeSet();
96     }
97 
98     /** Returns the name of the property. */
getPropertyName()99     public @NonNull String getPropertyName() {
100         return mPropertyName;
101     }
102 
103     /** Returns {@code String} values in an array. */
getStringValues()104     public String @Nullable [] getStringValues() {
105         return mStringValues;
106     }
107 
108     /** Returns {@code long} values in an array. */
getLongValues()109     public long @Nullable [] getLongValues() {
110         return mLongValues;
111     }
112 
113     /** Returns {@code double} values in an array. */
getDoubleValues()114     public double @Nullable [] getDoubleValues() {
115         return mDoubleValues;
116     }
117 
118     /** Returns {@code boolean} values in an array. */
getBooleanValues()119     public boolean @Nullable [] getBooleanValues() {
120         return mBooleanValues;
121     }
122 
123     /** Returns a two-dimension {@code byte} array. */
getBytesValues()124     public byte @Nullable [][] getBytesValues() {
125         return mBytesValues;
126     }
127 
128     /** Returns {@link GenericDocumentParcel}s in an array. */
getDocumentValues()129     public GenericDocumentParcel @Nullable [] getDocumentValues() {
130         return mDocumentValues;
131     }
132 
133     /** Returns {@link EmbeddingVector}s in an array. */
getEmbeddingValues()134     public EmbeddingVector @Nullable [] getEmbeddingValues() {
135         return mEmbeddingValues;
136     }
137 
138     /** Returns {@link AppSearchBlobHandle}s in an array. */
getBlobHandleValues()139     public AppSearchBlobHandle @Nullable [] getBlobHandleValues() {
140         return mBlobHandleValues;
141     }
142 
143     /**
144      * Returns the held values in an array for this property.
145      *
146      * <p>Different from other getter methods, this one will return an {@link Object}.
147      */
getValues()148     public @Nullable Object getValues() {
149         if (mStringValues != null) {
150             return mStringValues;
151         }
152         if (mLongValues != null) {
153             return mLongValues;
154         }
155         if (mDoubleValues != null) {
156             return mDoubleValues;
157         }
158         if (mBooleanValues != null) {
159             return mBooleanValues;
160         }
161         if (mBytesValues != null) {
162             return mBytesValues;
163         }
164         if (mDocumentValues != null) {
165             return mDocumentValues;
166         }
167         if (mEmbeddingValues != null) {
168             return mEmbeddingValues;
169         }
170         if (mBlobHandleValues != null) {
171             return mBlobHandleValues;
172         }
173         return null;
174     }
175 
176     /**
177      * Checks there is one and only one array can be set for the property.
178      *
179      * @throws IllegalArgumentException if 0, or more than 1 arrays are set.
180      */
checkOnlyOneArrayCanBeSet()181     private void checkOnlyOneArrayCanBeSet() {
182         int notNullCount = 0;
183         if (mStringValues != null) {
184             ++notNullCount;
185         }
186         if (mLongValues != null) {
187             ++notNullCount;
188         }
189         if (mDoubleValues != null) {
190             ++notNullCount;
191         }
192         if (mBooleanValues != null) {
193             ++notNullCount;
194         }
195         if (mBytesValues != null) {
196             ++notNullCount;
197         }
198         if (mDocumentValues != null) {
199             ++notNullCount;
200         }
201         if (mEmbeddingValues != null) {
202             ++notNullCount;
203         }
204         if (mBlobHandleValues != null) {
205             ++notNullCount;
206         }
207         if (notNullCount == 0 || notNullCount > 1) {
208             throw new IllegalArgumentException(
209                     "One and only one type array can be set in PropertyParcel");
210         }
211     }
212 
213     @Override
hashCode()214     public int hashCode() {
215         if (mHashCode == null) {
216             int hashCode = 0;
217             if (mStringValues != null) {
218                 hashCode = Arrays.hashCode(mStringValues);
219             } else if (mLongValues != null) {
220                 hashCode = Arrays.hashCode(mLongValues);
221             } else if (mDoubleValues != null) {
222                 hashCode = Arrays.hashCode(mDoubleValues);
223             } else if (mBooleanValues != null) {
224                 hashCode = Arrays.hashCode(mBooleanValues);
225             } else if (mBytesValues != null) {
226                 hashCode = Arrays.deepHashCode(mBytesValues);
227             } else if (mDocumentValues != null) {
228                 hashCode = Arrays.hashCode(mDocumentValues);
229             } else if (mEmbeddingValues != null) {
230                 hashCode = Arrays.deepHashCode(mEmbeddingValues);
231             } else if (mBlobHandleValues != null) {
232                 hashCode = Arrays.deepHashCode(mBlobHandleValues);
233             }
234             mHashCode = Objects.hash(mPropertyName, hashCode);
235         }
236         return mHashCode;
237     }
238 
239     @Override
equals(@ullable Object other)240     public boolean equals(@Nullable Object other) {
241         if (this == other) {
242             return true;
243         }
244         if (!(other instanceof PropertyParcel)) {
245             return false;
246         }
247         PropertyParcel otherPropertyParcel = (PropertyParcel) other;
248         if (!mPropertyName.equals(otherPropertyParcel.mPropertyName)) {
249             return false;
250         }
251         return Arrays.equals(mStringValues, otherPropertyParcel.mStringValues)
252                 && Arrays.equals(mLongValues, otherPropertyParcel.mLongValues)
253                 && Arrays.equals(mDoubleValues, otherPropertyParcel.mDoubleValues)
254                 && Arrays.equals(mBooleanValues, otherPropertyParcel.mBooleanValues)
255                 && Arrays.deepEquals(mBytesValues, otherPropertyParcel.mBytesValues)
256                 && Arrays.equals(mDocumentValues, otherPropertyParcel.mDocumentValues)
257                 && Arrays.deepEquals(mEmbeddingValues, otherPropertyParcel.mEmbeddingValues)
258                 && Arrays.deepEquals(mBlobHandleValues, otherPropertyParcel.mBlobHandleValues);
259     }
260 
261     @Override
writeToParcel(@onNull Parcel dest, int flags)262     public void writeToParcel(@NonNull Parcel dest, int flags) {
263         PropertyParcelCreator.writeToParcel(this, dest, flags);
264     }
265 
266     /** Builder for {@link PropertyParcel}. */
267     public static final class Builder {
268         private String mPropertyName;
269         private String[] mStringValues;
270         private long[] mLongValues;
271         private double[] mDoubleValues;
272         private boolean[] mBooleanValues;
273         private byte[][] mBytesValues;
274         private GenericDocumentParcel[] mDocumentValues;
275         private EmbeddingVector[] mEmbeddingValues;
276         private AppSearchBlobHandle[] mBlobHandleValues;
277 
Builder(@onNull String propertyName)278         public Builder(@NonNull String propertyName) {
279             mPropertyName = Objects.requireNonNull(propertyName);
280         }
281 
282         /** Sets String values. */
283         @CanIgnoreReturnValue
setStringValues(String @onNull [] stringValues)284         public @NonNull Builder setStringValues(String @NonNull [] stringValues) {
285             mStringValues = Objects.requireNonNull(stringValues);
286             return this;
287         }
288 
289         /** Sets long values. */
290         @CanIgnoreReturnValue
setLongValues(long @NonNull [] longValues)291         public @NonNull Builder setLongValues(long @NonNull [] longValues) {
292             mLongValues = Objects.requireNonNull(longValues);
293             return this;
294         }
295 
296         /** Sets double values. */
297         @CanIgnoreReturnValue
setDoubleValues(double @NonNull [] doubleValues)298         public @NonNull Builder setDoubleValues(double @NonNull [] doubleValues) {
299             mDoubleValues = Objects.requireNonNull(doubleValues);
300             return this;
301         }
302 
303         /** Sets boolean values. */
304         @CanIgnoreReturnValue
setBooleanValues(boolean @NonNull [] booleanValues)305         public @NonNull Builder setBooleanValues(boolean @NonNull [] booleanValues) {
306             mBooleanValues = Objects.requireNonNull(booleanValues);
307             return this;
308         }
309 
310         /** Sets a two dimension byte array. */
311         @CanIgnoreReturnValue
setBytesValues(byte @NonNull [][] bytesValues)312         public @NonNull Builder setBytesValues(byte @NonNull [][] bytesValues) {
313             mBytesValues = Objects.requireNonNull(bytesValues);
314             return this;
315         }
316 
317         /** Sets document values. */
318         @CanIgnoreReturnValue
setDocumentValues( GenericDocumentParcel @onNull [] documentValues)319         public @NonNull Builder setDocumentValues(
320                 GenericDocumentParcel @NonNull [] documentValues) {
321             mDocumentValues = Objects.requireNonNull(documentValues);
322             return this;
323         }
324 
325         /** Sets embedding values. */
326         @CanIgnoreReturnValue
setEmbeddingValues(EmbeddingVector @onNull [] embeddingValues)327         public @NonNull Builder setEmbeddingValues(EmbeddingVector @NonNull [] embeddingValues) {
328             mEmbeddingValues = Objects.requireNonNull(embeddingValues);
329             return this;
330         }
331 
332         /** Sets {@link AppSearchBlobHandle} values. */
333         @CanIgnoreReturnValue
setBlobHandleValues( AppSearchBlobHandle @onNull [] blobHandleValues)334         public @NonNull Builder setBlobHandleValues(
335                 AppSearchBlobHandle @NonNull [] blobHandleValues) {
336             mBlobHandleValues = Objects.requireNonNull(blobHandleValues);
337             return this;
338         }
339 
340         /** Builds a {@link PropertyParcel}. */
build()341         public @NonNull PropertyParcel build() {
342             return new PropertyParcel(
343                     mPropertyName,
344                     mStringValues,
345                     mLongValues,
346                     mDoubleValues,
347                     mBooleanValues,
348                     mBytesValues,
349                     mDocumentValues,
350                     mEmbeddingValues,
351                     mBlobHandleValues);
352         }
353     }
354 }
355