/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.appsearch.contactsindexer; import android.annotation.IntDef; import android.annotation.NonNull; import android.util.ArraySet; import com.android.server.appsearch.stats.AppSearchStatsLog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Set; /** * The class to hold stats for DeltaUpdate or FullUpdate. * *

This will be used to populate {@link * AppSearchStatsLog#CONTACTS_INDEXER_UPDATE_STATS_REPORTED}. * *

This class is not thread-safe. * * @hide */ public class ContactsUpdateStats { @IntDef( value = { UNKNOWN_UPDATE_TYPE, DELTA_UPDATE, FULL_UPDATE, }) @Retention(RetentionPolicy.SOURCE) public @interface UpdateType {} public static final int UNKNOWN_UPDATE_TYPE = AppSearchStatsLog.CONTACTS_INDEXER_UPDATE_STATS_REPORTED__UPDATE_TYPE__UNKNOWN; /** Incremental update reacting to CP2 change notifications. */ public static final int DELTA_UPDATE = AppSearchStatsLog.CONTACTS_INDEXER_UPDATE_STATS_REPORTED__UPDATE_TYPE__DELTA; /** Complete update to bring AppSearch in sync with CP2. */ public static final int FULL_UPDATE = AppSearchStatsLog.CONTACTS_INDEXER_UPDATE_STATS_REPORTED__UPDATE_TYPE__FULL; @IntDef( value = { ERROR_CODE_CP2_RUNTIME_EXCEPTION, ERROR_CODE_CP2_NULL_CURSOR, ERROR_CODE_APP_SEARCH_SYSTEM_ERROR, ERROR_CODE_CONTACTS_INDEXER_UNKNOWN_ERROR, }) @Retention(RetentionPolicy.SOURCE) public @interface ErrorCode {} // Error code logged from CP2 runtime exceptions public static final int ERROR_CODE_CP2_RUNTIME_EXCEPTION = 10000; // Error code logged from CP2 null query cursors public static final int ERROR_CODE_CP2_NULL_CURSOR = 10001; // Error code logged from AppSearch system errors. This code may be combined with an // AppSearchResult code from toFailedResult on the throwable from onSystemError(). public static final int ERROR_CODE_APP_SEARCH_SYSTEM_ERROR = 10100; // Error code logged from ContactsIndexer for otherwise uncaught exceptions public static final int ERROR_CODE_CONTACTS_INDEXER_UNKNOWN_ERROR = 10200; @UpdateType int mUpdateType = UNKNOWN_UPDATE_TYPE; // Status for updates. // In case of success, we will just have one success status stored. // In case of Error, we store the unique error codes during the update. Set mUpdateStatuses = new ArraySet<>(); // Status for deletions. // In case of success, we will just have one success status stored. // In case of Error, we store the unique error codes during the deletion. Set mDeleteStatuses = new ArraySet<>(); // Start time in millis for update and delete. long mUpdateAndDeleteStartTimeMillis; // Start time in millis for last full update long mLastFullUpdateStartTimeMillis; // Start time in millis for last delta update long mLastDeltaUpdateStartTimeMillis; // Time in millis of last contact updated from CP2 long mLastContactUpdatedTimeMillis; // Time in millis of last contact deleted from CP2 long mLastContactDeletedTimeMillis; // The mLastContactUpdatedTimeMillis from the previous update. This field is logged only for // full updates and should match the current mLastContactUpdatedTimeMillis. // Delta updates are run in response to CP2 notifications, so we expect the last contact updated // to have changed. Full updates are scheduled as a fix/maintenance job, so it's not expected // for the last contact updated to have changed. It's possible that a full update lands right as // a contact is updated, but we expect this to happen very rarely or not at all. There is an // issue if we find that these timestamps frequently do not match. long mPreviousLastContactUpdatedTimeMillis; // // Update for both old and new contacts(a.k.a insertion). // // # of old and new contacts failed to be updated. int mContactsUpdateFailedCount; // # of old and new contacts succeeds to be updated. int mContactsUpdateSucceededCount; // # of contacts update skipped due to NO significant change during the update. int mContactsUpdateSkippedCount; // Total # of old and new contacts to be updated. // It should equal to // mContactsUpdateFailedCount + mContactsUpdateSucceededCount + mContactsUpdateSkippedCount int mTotalContactsToBeUpdated; // Among the succeeded and failed contacts updates, how many of them are for the new contacts // currently NOT available in AppSearch. int mNewContactsToBeUpdated; // // Deletion for old documents. // // # of old contacts that failed to be deleted. This includes contacts that were not found. int mContactsDeleteFailedCount; // # of old contacts that were deleted successfully. int mContactsDeleteSucceededCount; // # of old contacts to be deleted that were not found. int mContactsDeleteNotFoundCount; // Total # of old contacts to be deleted. It should equal // mContactsDeleteFailedCount + mContactsDeleteSucceededCount int mTotalContactsToBeDeleted; public void clear() { mUpdateType = UNKNOWN_UPDATE_TYPE; mUpdateStatuses.clear(); mDeleteStatuses.clear(); mUpdateAndDeleteStartTimeMillis = 0; mLastFullUpdateStartTimeMillis = 0; mLastDeltaUpdateStartTimeMillis = 0; mLastContactUpdatedTimeMillis = 0; mLastContactDeletedTimeMillis = 0; mPreviousLastContactUpdatedTimeMillis = 0; // Update for old and new contacts mContactsUpdateFailedCount = 0; mContactsUpdateSucceededCount = 0; mContactsUpdateSkippedCount = 0; mNewContactsToBeUpdated = 0; mTotalContactsToBeUpdated = 0; // delete for old contacts mContactsDeleteFailedCount = 0; mContactsDeleteSucceededCount = 0; mContactsDeleteNotFoundCount = 0; mTotalContactsToBeDeleted = 0; } @NonNull public String toString() { return "UpdateType: " + mUpdateType + ", UpdateStatus: " + mUpdateStatuses.toString() + ", DeleteStatus: " + mDeleteStatuses.toString() + ", UpdateAndDeleteStartTimeMillis: " + mUpdateAndDeleteStartTimeMillis + ", LastFullUpdateStartTimeMillis: " + mLastFullUpdateStartTimeMillis + ", LastDeltaUpdateStartTimeMillis: " + mLastDeltaUpdateStartTimeMillis + ", LastContactUpdatedTimeMillis: " + mLastContactUpdatedTimeMillis + ", LastContactDeletedTimeMillis: " + mLastContactDeletedTimeMillis + ", PreviousLastContactUpdatedTimeMillis: " + mPreviousLastContactUpdatedTimeMillis + ", ContactsUpdateFailedCount: " + mContactsUpdateFailedCount + ", ContactsUpdateSucceededCount: " + mContactsUpdateSucceededCount + ", NewContactsToBeUpdated: " + mNewContactsToBeUpdated + ", ContactsUpdateSkippedCount: " + mContactsUpdateSkippedCount + ", TotalContactsToBeUpdated: " + mTotalContactsToBeUpdated + ", ContactsDeleteFailedCount: " + mContactsDeleteFailedCount + ", ContactsDeleteSucceededCount: " + mContactsDeleteSucceededCount + ", ContactsDeleteNotFoundCount: " + mContactsDeleteNotFoundCount + ", TotalContactsToBeDeleted: " + mTotalContactsToBeDeleted; } }