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 com.android.server.appsearch.contactsindexer;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.util.ArraySet;
22 
23 import com.android.server.appsearch.stats.AppSearchStatsLog;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.util.Set;
28 
29 /**
30  * The class to hold stats for DeltaUpdate or FullUpdate.
31  *
32  * <p>This will be used to populate {@link
33  * AppSearchStatsLog#CONTACTS_INDEXER_UPDATE_STATS_REPORTED}.
34  *
35  * <p>This class is not thread-safe.
36  *
37  * @hide
38  */
39 public class ContactsUpdateStats {
40     @IntDef(
41             value = {
42                 UNKNOWN_UPDATE_TYPE,
43                 DELTA_UPDATE,
44                 FULL_UPDATE,
45             })
46     @Retention(RetentionPolicy.SOURCE)
47     public @interface UpdateType {}
48 
49     public static final int UNKNOWN_UPDATE_TYPE =
50             AppSearchStatsLog.CONTACTS_INDEXER_UPDATE_STATS_REPORTED__UPDATE_TYPE__UNKNOWN;
51 
52     /** Incremental update reacting to CP2 change notifications. */
53     public static final int DELTA_UPDATE =
54             AppSearchStatsLog.CONTACTS_INDEXER_UPDATE_STATS_REPORTED__UPDATE_TYPE__DELTA;
55 
56     /** Complete update to bring AppSearch in sync with CP2. */
57     public static final int FULL_UPDATE =
58             AppSearchStatsLog.CONTACTS_INDEXER_UPDATE_STATS_REPORTED__UPDATE_TYPE__FULL;
59 
60     @IntDef(
61             value = {
62                 ERROR_CODE_CP2_RUNTIME_EXCEPTION,
63                 ERROR_CODE_CP2_NULL_CURSOR,
64                 ERROR_CODE_APP_SEARCH_SYSTEM_ERROR,
65                 ERROR_CODE_CONTACTS_INDEXER_UNKNOWN_ERROR,
66             })
67     @Retention(RetentionPolicy.SOURCE)
68     public @interface ErrorCode {}
69 
70     // Error code logged from CP2 runtime exceptions
71     public static final int ERROR_CODE_CP2_RUNTIME_EXCEPTION = 10000;
72     // Error code logged from CP2 null query cursors
73     public static final int ERROR_CODE_CP2_NULL_CURSOR = 10001;
74     // Error code logged from AppSearch system errors. This code may be combined with an
75     // AppSearchResult code from toFailedResult on the throwable from onSystemError().
76     public static final int ERROR_CODE_APP_SEARCH_SYSTEM_ERROR = 10100;
77     // Error code logged from ContactsIndexer for otherwise uncaught exceptions
78     public static final int ERROR_CODE_CONTACTS_INDEXER_UNKNOWN_ERROR = 10200;
79 
80     @UpdateType int mUpdateType = UNKNOWN_UPDATE_TYPE;
81     // Status for updates.
82     // In case of success, we will just have one success status stored.
83     // In case of Error,  we store the unique error codes during the update.
84     Set<Integer> mUpdateStatuses = new ArraySet<>();
85     // Status for deletions.
86     // In case of success, we will just have one success status stored.
87     // In case of Error,  we store the unique error codes during the deletion.
88     Set<Integer> mDeleteStatuses = new ArraySet<>();
89 
90     // Start time in millis for update and delete.
91     long mUpdateAndDeleteStartTimeMillis;
92     // Start time in millis for last full update
93     long mLastFullUpdateStartTimeMillis;
94     // Start time in millis for last delta update
95     long mLastDeltaUpdateStartTimeMillis;
96     // Time in millis of last contact updated from CP2
97     long mLastContactUpdatedTimeMillis;
98     // Time in millis of last contact deleted from CP2
99     long mLastContactDeletedTimeMillis;
100     // The mLastContactUpdatedTimeMillis from the previous update. This field is logged only for
101     // full updates and should match the current mLastContactUpdatedTimeMillis.
102     // Delta updates are run in response to CP2 notifications, so we expect the last contact updated
103     // to have changed. Full updates are scheduled as a fix/maintenance job, so it's not expected
104     // for the last contact updated to have changed. It's possible that a full update lands right as
105     // a contact is updated, but we expect this to happen very rarely or not at all. There is an
106     // issue if we find that these timestamps frequently do not match.
107     long mPreviousLastContactUpdatedTimeMillis;
108 
109     //
110     // Update for both old and new contacts(a.k.a insertion).
111     //
112     // # of old and new contacts failed to be updated.
113     int mContactsUpdateFailedCount;
114     // # of old and new contacts succeeds to be updated.
115     int mContactsUpdateSucceededCount;
116     // # of contacts update skipped due to NO significant change during the update.
117     int mContactsUpdateSkippedCount;
118     // Total # of old and new contacts to be updated.
119     // It should equal to
120     // mContactsUpdateFailedCount + mContactsUpdateSucceededCount + mContactsUpdateSkippedCount
121     int mTotalContactsToBeUpdated;
122     // Among the succeeded and failed contacts updates, how many of them are for the new contacts
123     // currently NOT available in AppSearch.
124     int mNewContactsToBeUpdated;
125 
126     //
127     // Deletion for old documents.
128     //
129     // # of old contacts that failed to be deleted. This includes contacts that were not found.
130     int mContactsDeleteFailedCount;
131     // # of old contacts that were deleted successfully.
132     int mContactsDeleteSucceededCount;
133     // # of old contacts to be deleted that were not found.
134     int mContactsDeleteNotFoundCount;
135     // Total # of old contacts to be deleted. It should equal
136     // mContactsDeleteFailedCount + mContactsDeleteSucceededCount
137     int mTotalContactsToBeDeleted;
138 
clear()139     public void clear() {
140         mUpdateType = UNKNOWN_UPDATE_TYPE;
141         mUpdateStatuses.clear();
142         mDeleteStatuses.clear();
143         mUpdateAndDeleteStartTimeMillis = 0;
144         mLastFullUpdateStartTimeMillis = 0;
145         mLastDeltaUpdateStartTimeMillis = 0;
146         mLastContactUpdatedTimeMillis = 0;
147         mLastContactDeletedTimeMillis = 0;
148         mPreviousLastContactUpdatedTimeMillis = 0;
149         // Update for old and new contacts
150         mContactsUpdateFailedCount = 0;
151         mContactsUpdateSucceededCount = 0;
152         mContactsUpdateSkippedCount = 0;
153         mNewContactsToBeUpdated = 0;
154         mTotalContactsToBeUpdated = 0;
155         // delete for old contacts
156         mContactsDeleteFailedCount = 0;
157         mContactsDeleteSucceededCount = 0;
158         mContactsDeleteNotFoundCount = 0;
159         mTotalContactsToBeDeleted = 0;
160     }
161 
162     @NonNull
toString()163     public String toString() {
164         return "UpdateType: "
165                 + mUpdateType
166                 + ", UpdateStatus: "
167                 + mUpdateStatuses.toString()
168                 + ", DeleteStatus: "
169                 + mDeleteStatuses.toString()
170                 + ", UpdateAndDeleteStartTimeMillis: "
171                 + mUpdateAndDeleteStartTimeMillis
172                 + ", LastFullUpdateStartTimeMillis: "
173                 + mLastFullUpdateStartTimeMillis
174                 + ", LastDeltaUpdateStartTimeMillis: "
175                 + mLastDeltaUpdateStartTimeMillis
176                 + ", LastContactUpdatedTimeMillis: "
177                 + mLastContactUpdatedTimeMillis
178                 + ", LastContactDeletedTimeMillis: "
179                 + mLastContactDeletedTimeMillis
180                 + ", PreviousLastContactUpdatedTimeMillis: "
181                 + mPreviousLastContactUpdatedTimeMillis
182                 + ", ContactsUpdateFailedCount: "
183                 + mContactsUpdateFailedCount
184                 + ", ContactsUpdateSucceededCount: "
185                 + mContactsUpdateSucceededCount
186                 + ", NewContactsToBeUpdated: "
187                 + mNewContactsToBeUpdated
188                 + ", ContactsUpdateSkippedCount: "
189                 + mContactsUpdateSkippedCount
190                 + ", TotalContactsToBeUpdated: "
191                 + mTotalContactsToBeUpdated
192                 + ", ContactsDeleteFailedCount: "
193                 + mContactsDeleteFailedCount
194                 + ", ContactsDeleteSucceededCount: "
195                 + mContactsDeleteSucceededCount
196                 + ", ContactsDeleteNotFoundCount: "
197                 + mContactsDeleteNotFoundCount
198                 + ", TotalContactsToBeDeleted: "
199                 + mTotalContactsToBeDeleted;
200     }
201 }
202