1 /*
2  * Copyright 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.stats;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.app.appsearch.AppSearchResult;
22 import android.app.appsearch.SetSchemaRequest;
23 import android.app.appsearch.annotation.CanIgnoreReturnValue;
24 import android.app.appsearch.safeparcel.AbstractSafeParcelable;
25 import android.app.appsearch.safeparcel.SafeParcelable;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 import java.util.Objects;
32 
33 /**
34  * Class holds detailed stats for Schema migration.
35  *
36  * @hide
37  */
38 @SafeParcelable.Class(creator = "SchemaMigrationStatsCreator")
39 public final class SchemaMigrationStats extends AbstractSafeParcelable {
40     @NonNull
41     public static final Parcelable.Creator<SchemaMigrationStats> CREATOR =
42             new SchemaMigrationStatsCreator();
43 
44     /** Indicate the SetSchema call type relative to SchemaMigration case. */
45     @IntDef(
46             value = {
47                 NO_MIGRATION,
48                 FIRST_CALL_GET_INCOMPATIBLE,
49                 SECOND_CALL_APPLY_NEW_SCHEMA,
50             })
51     @Retention(RetentionPolicy.SOURCE)
52     public @interface SchemaMigrationCallType {}
53 
54     /** This SetSchema call is not relative to a SchemaMigration case. */
55     public static final int NO_MIGRATION = 0;
56 
57     /** This is the first SetSchema call in Migration cases to get all incompatible changes. */
58     public static final int FIRST_CALL_GET_INCOMPATIBLE = 1;
59 
60     /** This is the second SetSchema call in Migration cases to apply new schema changes */
61     public static final int SECOND_CALL_APPLY_NEW_SCHEMA = 2;
62 
63     @Field(id = 1, getter = "getPackageName")
64     @NonNull
65     private final String mPackageName;
66 
67     @Field(id = 2, getter = "getDatabase")
68     @NonNull
69     private final String mDatabase;
70 
71     @Field(id = 3, getter = "getStatusCode")
72     private final int mStatusCode;
73 
74     @Field(id = 4, getter = "getExecutorAcquisitionLatencyMillis")
75     private final int mExecutorAcquisitionLatencyMillis;
76 
77     @Field(id = 5, getter = "getTotalLatencyMillis")
78     private final int mTotalLatencyMillis;
79 
80     @Field(id = 6, getter = "getGetSchemaLatencyMillis")
81     private final int mGetSchemaLatencyMillis;
82 
83     @Field(id = 7, getter = "getQueryAndTransformLatencyMillis")
84     private final int mQueryAndTransformLatencyMillis;
85 
86     @Field(id = 8, getter = "getFirstSetSchemaLatencyMillis")
87     private final int mFirstSetSchemaLatencyMillis;
88 
89     @Field(id = 9, getter = "isFirstSetSchemaSuccess")
90     private final boolean mIsFirstSetSchemaSuccess;
91 
92     @Field(id = 10, getter = "getSecondSetSchemaLatencyMillis")
93     private final int mSecondSetSchemaLatencyMillis;
94 
95     @Field(id = 11, getter = "getSaveDocumentLatencyMillis")
96     private final int mSaveDocumentLatencyMillis;
97 
98     @Field(id = 12, getter = "getTotalNeedMigratedDocumentCount")
99     private final int mTotalNeedMigratedDocumentCount;
100 
101     @Field(id = 13, getter = "getMigrationFailureCount")
102     private final int mMigrationFailureCount;
103 
104     @Field(id = 14, getter = "getTotalSuccessMigratedDocumentCount")
105     private final int mTotalSuccessMigratedDocumentCount;
106 
107     /** Build a {@link SchemaMigrationStats} from the given parameters. */
108     @Constructor
SchemaMigrationStats( @aramid = 1) @onNull String packageName, @Param(id = 2) @NonNull String database, @Param(id = 3) int statusCode, @Param(id = 4) int executorAcquisitionLatencyMillis, @Param(id = 5) int totalLatencyMillis, @Param(id = 6) int getSchemaLatencyMillis, @Param(id = 7) int queryAndTransformLatencyMillis, @Param(id = 8) int firstSetSchemaLatencyMillis, @Param(id = 9) boolean isFirstSetSchemaSuccess, @Param(id = 10) int secondSetSchemaLatencyMillis, @Param(id = 11) int saveDocumentLatencyMillis, @Param(id = 12) int totalNeedMigratedDocumentCount, @Param(id = 13) int migrationFailureCount, @Param(id = 14) int totalSuccessMigratedDocumentCount)109     public SchemaMigrationStats(
110             @Param(id = 1) @NonNull String packageName,
111             @Param(id = 2) @NonNull String database,
112             @Param(id = 3) int statusCode,
113             @Param(id = 4) int executorAcquisitionLatencyMillis,
114             @Param(id = 5) int totalLatencyMillis,
115             @Param(id = 6) int getSchemaLatencyMillis,
116             @Param(id = 7) int queryAndTransformLatencyMillis,
117             @Param(id = 8) int firstSetSchemaLatencyMillis,
118             @Param(id = 9) boolean isFirstSetSchemaSuccess,
119             @Param(id = 10) int secondSetSchemaLatencyMillis,
120             @Param(id = 11) int saveDocumentLatencyMillis,
121             @Param(id = 12) int totalNeedMigratedDocumentCount,
122             @Param(id = 13) int migrationFailureCount,
123             @Param(id = 14) int totalSuccessMigratedDocumentCount) {
124         mPackageName = packageName;
125         mDatabase = database;
126         mStatusCode = statusCode;
127         mExecutorAcquisitionLatencyMillis = executorAcquisitionLatencyMillis;
128         mTotalLatencyMillis = totalLatencyMillis;
129         mGetSchemaLatencyMillis = getSchemaLatencyMillis;
130         mQueryAndTransformLatencyMillis = queryAndTransformLatencyMillis;
131         mFirstSetSchemaLatencyMillis = firstSetSchemaLatencyMillis;
132         mIsFirstSetSchemaSuccess = isFirstSetSchemaSuccess;
133         mSecondSetSchemaLatencyMillis = secondSetSchemaLatencyMillis;
134         mSaveDocumentLatencyMillis = saveDocumentLatencyMillis;
135         mTotalNeedMigratedDocumentCount = totalNeedMigratedDocumentCount;
136         mMigrationFailureCount = migrationFailureCount;
137         mTotalSuccessMigratedDocumentCount = totalSuccessMigratedDocumentCount;
138     }
139 
140     /** Returns calling package name. */
141     @NonNull
getPackageName()142     public String getPackageName() {
143         return mPackageName;
144     }
145 
146     /** Returns calling database name. */
147     @NonNull
getDatabase()148     public String getDatabase() {
149         return mDatabase;
150     }
151 
152     /** Returns status of the schema migration action. */
153     @AppSearchResult.ResultCode
getStatusCode()154     public int getStatusCode() {
155         return mStatusCode;
156     }
157 
158     /** Gets the latency for waiting the executor. */
getExecutorAcquisitionLatencyMillis()159     public int getExecutorAcquisitionLatencyMillis() {
160         return mExecutorAcquisitionLatencyMillis;
161     }
162 
163     /** Gets total latency for the schema migration action in milliseconds. */
getTotalLatencyMillis()164     public int getTotalLatencyMillis() {
165         return mTotalLatencyMillis;
166     }
167 
168     /** Returns GetSchema latency in milliseconds. */
getGetSchemaLatencyMillis()169     public int getGetSchemaLatencyMillis() {
170         return mGetSchemaLatencyMillis;
171     }
172 
173     /**
174      * Returns latency of querying all documents that need to be migrated to new version and
175      * transforming documents to new version in milliseconds.
176      */
getQueryAndTransformLatencyMillis()177     public int getQueryAndTransformLatencyMillis() {
178         return mQueryAndTransformLatencyMillis;
179     }
180 
181     /**
182      * Returns latency of first SetSchema action in milliseconds.
183      *
184      * <p>If all schema fields are backward compatible, the schema will be successful set to Icing.
185      * Otherwise, we will retrieve incompatible types here.
186      *
187      * <p>Please see {@link SetSchemaRequest} for what is "incompatible".
188      */
getFirstSetSchemaLatencyMillis()189     public int getFirstSetSchemaLatencyMillis() {
190         return mFirstSetSchemaLatencyMillis;
191     }
192 
193     /** Returns whether the first SetSchema action success. */
isFirstSetSchemaSuccess()194     public boolean isFirstSetSchemaSuccess() {
195         return mIsFirstSetSchemaSuccess;
196     }
197 
198     /**
199      * Returns latency of second SetSchema action in milliseconds.
200      *
201      * <p>If all schema fields are backward compatible, the schema will be successful set to Icing
202      * in the first setSchema action and this value will be 0. Otherwise, schema types will be set
203      * to Icing by this action.
204      */
getSecondSetSchemaLatencyMillis()205     public int getSecondSetSchemaLatencyMillis() {
206         return mSecondSetSchemaLatencyMillis;
207     }
208 
209     /** Returns latency of putting migrated document to Icing lib in milliseconds. */
getSaveDocumentLatencyMillis()210     public int getSaveDocumentLatencyMillis() {
211         return mSaveDocumentLatencyMillis;
212     }
213 
214     /** Returns number of document that need to be migrated to another version. */
getTotalNeedMigratedDocumentCount()215     public int getTotalNeedMigratedDocumentCount() {
216         return mTotalNeedMigratedDocumentCount;
217     }
218 
219     /** Returns number of {@link android.app.appsearch.SetSchemaResponse.MigrationFailure}. */
getMigrationFailureCount()220     public int getMigrationFailureCount() {
221         return mMigrationFailureCount;
222     }
223 
224     /** Returns number of successfully migrated and saved in Icing. */
getTotalSuccessMigratedDocumentCount()225     public int getTotalSuccessMigratedDocumentCount() {
226         return mTotalSuccessMigratedDocumentCount;
227     }
228 
229     @Override
writeToParcel(@onNull Parcel dest, int flags)230     public void writeToParcel(@NonNull Parcel dest, int flags) {
231         SchemaMigrationStatsCreator.writeToParcel(this, dest, flags);
232     }
233 
234     /** Builder for {@link SchemaMigrationStats}. */
235     public static class Builder {
236 
237         String mPackageName;
238         String mDatabase;
239         int mStatusCode;
240         int mExecutorAcquisitionLatencyMillis;
241         int mTotalLatencyMillis;
242         int mGetSchemaLatencyMillis;
243         int mQueryAndTransformLatencyMillis;
244         int mFirstSetSchemaLatencyMillis;
245         boolean mIsFirstSetSchemaSuccess;
246         int mSecondSetSchemaLatencyMillis;
247         int mSaveDocumentLatencyMillis;
248         int mTotalNeedMigratedDocumentCount;
249         int mMigrationFailureCount;
250         int mTotalSuccessMigratedDocumentCount;
251 
252         /** Creates a {@link SchemaMigrationStats.Builder}. */
Builder(@onNull String packageName, @NonNull String database)253         public Builder(@NonNull String packageName, @NonNull String database) {
254             mPackageName = Objects.requireNonNull(packageName);
255             mDatabase = Objects.requireNonNull(database);
256         }
257 
258         /**
259          * Creates a {@link SchemaMigrationStats.Builder} from a given {@link SchemaMigrationStats}.
260          *
261          * <p>The returned builder is a deep copy whose data is separate from this
262          * SchemaMigrationStats.
263          */
Builder(@onNull SchemaMigrationStats stats)264         public Builder(@NonNull SchemaMigrationStats stats) {
265             Objects.requireNonNull(stats);
266 
267             mPackageName = stats.mPackageName;
268             mDatabase = stats.mDatabase;
269             mStatusCode = stats.mStatusCode;
270             mExecutorAcquisitionLatencyMillis = stats.mExecutorAcquisitionLatencyMillis;
271             mTotalLatencyMillis = stats.mTotalLatencyMillis;
272             mGetSchemaLatencyMillis = stats.mGetSchemaLatencyMillis;
273             mQueryAndTransformLatencyMillis = stats.mQueryAndTransformLatencyMillis;
274             mFirstSetSchemaLatencyMillis = stats.mFirstSetSchemaLatencyMillis;
275             mIsFirstSetSchemaSuccess = stats.mIsFirstSetSchemaSuccess;
276             mSecondSetSchemaLatencyMillis = stats.mSecondSetSchemaLatencyMillis;
277             mSaveDocumentLatencyMillis = stats.mSaveDocumentLatencyMillis;
278             mTotalNeedMigratedDocumentCount = stats.mTotalNeedMigratedDocumentCount;
279             mMigrationFailureCount = stats.mMigrationFailureCount;
280             mTotalSuccessMigratedDocumentCount = stats.mTotalSuccessMigratedDocumentCount;
281         }
282 
283         /** Sets status code for the schema migration action. */
284         @CanIgnoreReturnValue
285         @NonNull
setStatusCode(@ppSearchResult.ResultCode int statusCode)286         public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) {
287             mStatusCode = statusCode;
288             return this;
289         }
290 
291         /** Sets the latency for waiting the executor. */
292         @CanIgnoreReturnValue
293         @NonNull
setExecutorAcquisitionLatencyMillis(int executorAcquisitionLatencyMillis)294         public Builder setExecutorAcquisitionLatencyMillis(int executorAcquisitionLatencyMillis) {
295             mExecutorAcquisitionLatencyMillis = executorAcquisitionLatencyMillis;
296             return this;
297         }
298 
299         /** Sets total latency for the schema migration action in milliseconds. */
300         @CanIgnoreReturnValue
301         @NonNull
setTotalLatencyMillis(int totalLatencyMillis)302         public Builder setTotalLatencyMillis(int totalLatencyMillis) {
303             mTotalLatencyMillis = totalLatencyMillis;
304             return this;
305         }
306 
307         /** Sets latency for the GetSchema action in milliseconds. */
308         @CanIgnoreReturnValue
309         @NonNull
setGetSchemaLatencyMillis(int getSchemaLatencyMillis)310         public Builder setGetSchemaLatencyMillis(int getSchemaLatencyMillis) {
311             mGetSchemaLatencyMillis = getSchemaLatencyMillis;
312             return this;
313         }
314 
315         /**
316          * Sets latency for querying all documents that need to be migrated to new version and
317          * transforming documents to new version in milliseconds.
318          */
319         @CanIgnoreReturnValue
320         @NonNull
setQueryAndTransformLatencyMillis(int queryAndTransformLatencyMillis)321         public Builder setQueryAndTransformLatencyMillis(int queryAndTransformLatencyMillis) {
322             mQueryAndTransformLatencyMillis = queryAndTransformLatencyMillis;
323             return this;
324         }
325 
326         /** Sets latency of first SetSchema action in milliseconds. */
327         @CanIgnoreReturnValue
328         @NonNull
setFirstSetSchemaLatencyMillis(int firstSetSchemaLatencyMillis)329         public Builder setFirstSetSchemaLatencyMillis(int firstSetSchemaLatencyMillis) {
330             mFirstSetSchemaLatencyMillis = firstSetSchemaLatencyMillis;
331             return this;
332         }
333 
334         /** Returns status of the first SetSchema action. */
335         @CanIgnoreReturnValue
336         @NonNull
setIsFirstSetSchemaSuccess(boolean isFirstSetSchemaSuccess)337         public Builder setIsFirstSetSchemaSuccess(boolean isFirstSetSchemaSuccess) {
338             mIsFirstSetSchemaSuccess = isFirstSetSchemaSuccess;
339             return this;
340         }
341 
342         /** Sets latency of second SetSchema action in milliseconds. */
343         @CanIgnoreReturnValue
344         @NonNull
setSecondSetSchemaLatencyMillis(int secondSetSchemaLatencyMillis)345         public Builder setSecondSetSchemaLatencyMillis(int secondSetSchemaLatencyMillis) {
346             mSecondSetSchemaLatencyMillis = secondSetSchemaLatencyMillis;
347             return this;
348         }
349 
350         /** Sets latency for putting migrated document to Icing lib in milliseconds. */
351         @CanIgnoreReturnValue
352         @NonNull
setSaveDocumentLatencyMillis(int saveDocumentLatencyMillis)353         public Builder setSaveDocumentLatencyMillis(int saveDocumentLatencyMillis) {
354             mSaveDocumentLatencyMillis = saveDocumentLatencyMillis;
355             return this;
356         }
357 
358         /** Sets number of document that need to be migrated to another version. */
359         @CanIgnoreReturnValue
360         @NonNull
setTotalNeedMigratedDocumentCount(int migratedDocumentCount)361         public Builder setTotalNeedMigratedDocumentCount(int migratedDocumentCount) {
362             mTotalNeedMigratedDocumentCount = migratedDocumentCount;
363             return this;
364         }
365 
366         /** Sets total document count of successfully migrated and saved in Icing. */
367         @CanIgnoreReturnValue
368         @NonNull
setTotalSuccessMigratedDocumentCount(int totalSuccessMigratedDocumentCount)369         public Builder setTotalSuccessMigratedDocumentCount(int totalSuccessMigratedDocumentCount) {
370             mTotalSuccessMigratedDocumentCount = totalSuccessMigratedDocumentCount;
371             return this;
372         }
373 
374         /** Sets number of {@link android.app.appsearch.SetSchemaResponse.MigrationFailure}. */
375         @CanIgnoreReturnValue
376         @NonNull
setMigrationFailureCount(int migrationFailureCount)377         public Builder setMigrationFailureCount(int migrationFailureCount) {
378             mMigrationFailureCount = migrationFailureCount;
379             return this;
380         }
381 
382         /**
383          * Builds a new {@link SchemaMigrationStats} from the {@link SchemaMigrationStats.Builder}.
384          */
385         @NonNull
build()386         public SchemaMigrationStats build() {
387             return new SchemaMigrationStats(
388                     mPackageName,
389                     mDatabase,
390                     mStatusCode,
391                     mExecutorAcquisitionLatencyMillis,
392                     mTotalLatencyMillis,
393                     mGetSchemaLatencyMillis,
394                     mQueryAndTransformLatencyMillis,
395                     mFirstSetSchemaLatencyMillis,
396                     mIsFirstSetSchemaSuccess,
397                     mSecondSetSchemaLatencyMillis,
398                     mSaveDocumentLatencyMillis,
399                     mTotalNeedMigratedDocumentCount,
400                     mMigrationFailureCount,
401                     mTotalSuccessMigratedDocumentCount);
402         }
403     }
404 }
405