diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java index c44fd40617a1..29048b25ad6f 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchConfig.java @@ -81,6 +81,14 @@ public final class AppSearchConfig implements AutoCloseable { "sampling_interval_for_batch_call_stats"; public static final String KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS = "sampling_interval_for_put_document_stats"; + public static final String KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS = + "sampling_interval_for_initialize_stats"; + public static final String KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS = + "sampling_interval_for_search_stats"; + public static final String KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS = + "sampling_interval_for_global_search_stats"; + public static final String KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS = + "sampling_interval_for_optimize_stats"; public static final String KEY_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES = "limit_config_max_document_size_bytes"; public static final String KEY_LIMIT_CONFIG_MAX_DOCUMENT_COUNT = @@ -95,6 +103,10 @@ public final class AppSearchConfig implements AutoCloseable { KEY_SAMPLING_INTERVAL_DEFAULT, KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS, KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS, + KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS, + KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS, + KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS, + KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS, KEY_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES, KEY_LIMIT_CONFIG_MAX_DOCUMENT_COUNT, KEY_BYTES_OPTIMIZE_THRESHOLD, @@ -245,6 +257,58 @@ public final class AppSearchConfig implements AutoCloseable { } } + /** + * Returns cached value for sampling interval for initialize. + * + *

For example, sampling_interval=10 means that one out of every 10 stats was logged. + */ + public int getCachedSamplingIntervalForInitializeStats() { + synchronized (mLock) { + throwIfClosedLocked(); + return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS, + getCachedSamplingIntervalDefault()); + } + } + + /** + * Returns cached value for sampling interval for search. + * + *

For example, sampling_interval=10 means that one out of every 10 stats was logged. + */ + public int getCachedSamplingIntervalForSearchStats() { + synchronized (mLock) { + throwIfClosedLocked(); + return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS, + getCachedSamplingIntervalDefault()); + } + } + + /** + * Returns cached value for sampling interval for globalSearch. + * + *

For example, sampling_interval=10 means that one out of every 10 stats was logged. + */ + public int getCachedSamplingIntervalForGlobalSearchStats() { + synchronized (mLock) { + throwIfClosedLocked(); + return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS, + getCachedSamplingIntervalDefault()); + } + } + + /** + * Returns cached value for sampling interval for optimize. + * + *

For example, sampling_interval=10 means that one out of every 10 stats was logged. + */ + public int getCachedSamplingIntervalForOptimizeStats() { + synchronized (mLock) { + throwIfClosedLocked(); + return mBundleLocked.getInt(KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS, + getCachedSamplingIntervalDefault()); + } + } + /** Returns the maximum serialized size an indexed document can be, in bytes. */ public int getCachedLimitConfigMaxDocumentSizeBytes() { synchronized (mLock) { @@ -343,6 +407,10 @@ public final class AppSearchConfig implements AutoCloseable { case KEY_SAMPLING_INTERVAL_DEFAULT: case KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS: case KEY_SAMPLING_INTERVAL_FOR_PUT_DOCUMENT_STATS: + case KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS: + case KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS: + case KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS: + case KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS: synchronized (mLock) { mBundleLocked.putInt(key, properties.getInt(key, DEFAULT_SAMPLING_INTERVAL)); } diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java index 1d66bebc81f9..db23a6dc3047 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -59,6 +59,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.server.LocalManagerRegistry; import com.android.server.SystemService; import com.android.server.appsearch.external.localstorage.stats.CallStats; +import com.android.server.appsearch.external.localstorage.stats.OptimizeStats; import com.android.server.appsearch.external.localstorage.visibilitystore.VisibilityStore; import com.android.server.appsearch.stats.StatsCollector; import com.android.server.appsearch.util.PackageUtil; @@ -1479,20 +1480,42 @@ public class AppSearchManagerService extends SystemService { private void checkForOptimize(AppSearchUserInstance instance, int mutateBatchSize) { EXECUTOR.execute(() -> { + long totalLatencyStartMillis = SystemClock.elapsedRealtime(); + OptimizeStats.Builder builder = new OptimizeStats.Builder(); try { - instance.getAppSearchImpl().checkForOptimize(mutateBatchSize); + instance.getAppSearchImpl().checkForOptimize(mutateBatchSize, builder); } catch (AppSearchException e) { Log.w(TAG, "Error occurred when check for optimize", e); + } finally { + OptimizeStats oStats = builder + .setTotalLatencyMillis( + (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis)) + .build(); + if (oStats.getOriginalDocumentCount() > 0) { + // see if optimize has been run by checking originalDocumentCount + instance.getLogger().logStats(oStats); + } } }); } private void checkForOptimize(AppSearchUserInstance instance) { EXECUTOR.execute(() -> { + long totalLatencyStartMillis = SystemClock.elapsedRealtime(); + OptimizeStats.Builder builder = new OptimizeStats.Builder(); try { - instance.getAppSearchImpl().checkForOptimize(); + instance.getAppSearchImpl().checkForOptimize(builder); } catch (AppSearchException e) { Log.w(TAG, "Error occurred when check for optimize", e); + } finally { + OptimizeStats oStats = builder + .setTotalLatencyMillis( + (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis)) + .build(); + if (oStats.getOriginalDocumentCount() > 0) { + // see if optimize has been run by checking originalDocumentCount + instance.getLogger().logStats(oStats); + } } }); } diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java index 830e76c62279..18e1ef58b668 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java @@ -55,6 +55,7 @@ import com.android.server.appsearch.external.localstorage.converter.SearchSpecTo import com.android.server.appsearch.external.localstorage.converter.SetSchemaResponseToProtoConverter; import com.android.server.appsearch.external.localstorage.converter.TypePropertyPathToProtoConverter; import com.android.server.appsearch.external.localstorage.stats.InitializeStats; +import com.android.server.appsearch.external.localstorage.stats.OptimizeStats; import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats; import com.android.server.appsearch.external.localstorage.stats.RemoveStats; import com.android.server.appsearch.external.localstorage.stats.SearchStats; @@ -284,6 +285,9 @@ public final class AppSearchImpl implements Closeable { // Log the time it took to read the data that goes into the cache maps if (initStatsBuilder != null) { + // In case there is some error for getAllNamespaces, we can still + // set the latency for preparation. + // If there is no error, the value will be overridden by the actual one later. initStatsBuilder .setStatusCode( statusProtoToResultCode( @@ -1326,8 +1330,7 @@ public final class AppSearchImpl implements Closeable { deleteResultProto.getStatus(), StatusProto.Code.OK, StatusProto.Code.NOT_FOUND); // Update derived maps - int numDocumentsDeleted = - deleteResultProto.getDeleteStats().getNumDocumentsDeleted(); + int numDocumentsDeleted = deleteResultProto.getDeleteStats().getNumDocumentsDeleted(); updateDocumentCountAfterRemovalLocked(packageName, numDocumentsDeleted); } finally { mReadWriteLock.writeLock().unlock(); @@ -2162,12 +2165,13 @@ public final class AppSearchImpl implements Closeable { * #CHECK_OPTIMIZE_INTERVAL}, {@link IcingSearchEngine#getOptimizeInfo()} will be triggered * and the counter will be reset. */ - public void checkForOptimize(int mutationSize) throws AppSearchException { + public void checkForOptimize(int mutationSize, @Nullable OptimizeStats.Builder builder) + throws AppSearchException { mReadWriteLock.writeLock().lock(); try { mOptimizeIntervalCountLocked += mutationSize; if (mOptimizeIntervalCountLocked >= CHECK_OPTIMIZE_INTERVAL) { - checkForOptimize(); + checkForOptimize(builder); } } finally { mReadWriteLock.writeLock().unlock(); @@ -2183,14 +2187,15 @@ public final class AppSearchImpl implements Closeable { *

{@link IcingSearchEngine#optimize()} should be called only if {@link * OptimizeStrategy#shouldOptimize(GetOptimizeInfoResultProto)} return true. */ - public void checkForOptimize() throws AppSearchException { + public void checkForOptimize(@Nullable OptimizeStats.Builder builder) + throws AppSearchException { mReadWriteLock.writeLock().lock(); try { GetOptimizeInfoResultProto optimizeInfo = getOptimizeInfoResultLocked(); checkSuccess(optimizeInfo.getStatus()); mOptimizeIntervalCountLocked = 0; if (mOptimizeStrategy.shouldOptimize(optimizeInfo)) { - optimize(); + optimize(builder); } } finally { mReadWriteLock.writeLock().unlock(); @@ -2201,13 +2206,18 @@ public final class AppSearchImpl implements Closeable { } /** Triggers {@link IcingSearchEngine#optimize()} directly. */ - public void optimize() throws AppSearchException { + public void optimize(@Nullable OptimizeStats.Builder builder) throws AppSearchException { mReadWriteLock.writeLock().lock(); try { mLogUtil.piiTrace("optimize, request"); OptimizeResultProto optimizeResultProto = mIcingSearchEngineLocked.optimize(); mLogUtil.piiTrace( "optimize, response", optimizeResultProto.getStatus(), optimizeResultProto); + if (builder != null) { + builder.setStatusCode(statusProtoToResultCode(optimizeResultProto.getStatus())); + AppSearchLoggerHelper.copyNativeStats( + optimizeResultProto.getOptimizeStats(), builder); + } checkSuccess(optimizeResultProto.getStatus()); } finally { mReadWriteLock.writeLock().unlock(); diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java index d92f4f05a1a4..98cedc7e6b54 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java @@ -17,10 +17,10 @@ package com.android.server.appsearch.external.localstorage; import android.annotation.NonNull; -import android.app.appsearch.exceptions.AppSearchException; import com.android.server.appsearch.external.localstorage.stats.CallStats; import com.android.server.appsearch.external.localstorage.stats.InitializeStats; +import com.android.server.appsearch.external.localstorage.stats.OptimizeStats; import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats; import com.android.server.appsearch.external.localstorage.stats.RemoveStats; import com.android.server.appsearch.external.localstorage.stats.SearchStats; @@ -37,19 +37,22 @@ import com.android.server.appsearch.external.localstorage.stats.SearchStats; */ public interface AppSearchLogger { /** Logs {@link CallStats} */ - void logStats(@NonNull CallStats stats) throws AppSearchException; + void logStats(@NonNull CallStats stats); /** Logs {@link PutDocumentStats} */ - void logStats(@NonNull PutDocumentStats stats) throws AppSearchException; + void logStats(@NonNull PutDocumentStats stats); /** Logs {@link InitializeStats} */ - void logStats(@NonNull InitializeStats stats) throws AppSearchException; + void logStats(@NonNull InitializeStats stats); /** Logs {@link SearchStats} */ - void logStats(@NonNull SearchStats stats) throws AppSearchException; + void logStats(@NonNull SearchStats stats); /** Logs {@link RemoveStats} */ - void logStats(@NonNull RemoveStats stats) throws AppSearchException; + void logStats(@NonNull RemoveStats stats); + + /** Logs {@link OptimizeStats} */ + void logStats(@NonNull OptimizeStats stats); // TODO(b/173532925) Add remaining logStats once we add all the stats. } diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java index aa9200abe3be..cd653e569f11 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java @@ -19,12 +19,14 @@ package com.android.server.appsearch.external.localstorage; import android.annotation.NonNull; import com.android.server.appsearch.external.localstorage.stats.InitializeStats; +import com.android.server.appsearch.external.localstorage.stats.OptimizeStats; import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats; import com.android.server.appsearch.external.localstorage.stats.RemoveStats; import com.android.server.appsearch.external.localstorage.stats.SearchStats; import com.google.android.icing.proto.DeleteStatsProto; import com.google.android.icing.proto.InitializeStatsProto; +import com.google.android.icing.proto.OptimizeStatsProto; import com.google.android.icing.proto.PutDocumentStatsProto; import com.google.android.icing.proto.QueryStatsProto; @@ -92,8 +94,8 @@ public final class AppSearchLoggerHelper { .setSchemaTypeCount(fromNativeStats.getNumSchemaTypes()); } - /* - * Copy native Query stats to buiilder. + /** + * Copies native Query stats to builder. * * @param fromNativeStats Stats copied from. * @param toStatsBuilder Stats copied to. @@ -122,8 +124,8 @@ public final class AppSearchLoggerHelper { fromNativeStats.getDocumentRetrievalLatencyMs()); } - /* - * Copy native Query stats to buiilder. + /** + * Copies native Delete stats to builder. * * @param fromNativeStats Stats copied from. * @param toStatsBuilder Stats copied to. @@ -138,4 +140,28 @@ public final class AppSearchLoggerHelper { .setDeleteType(fromNativeStats.getDeleteType().getNumber()) .setDeletedDocumentCount(fromNativeStats.getNumDocumentsDeleted()); } + + /** + * Copies native {@link OptimizeStatsProto} to builder. + * + * @param fromNativeStats Stats copied from. + * @param toStatsBuilder Stats copied to. + */ + static void copyNativeStats( + @NonNull OptimizeStatsProto fromNativeStats, + @NonNull OptimizeStats.Builder toStatsBuilder) { + Objects.requireNonNull(fromNativeStats); + Objects.requireNonNull(toStatsBuilder); + toStatsBuilder + .setNativeLatencyMillis(fromNativeStats.getLatencyMs()) + .setDocumentStoreOptimizeLatencyMillis( + fromNativeStats.getDocumentStoreOptimizeLatencyMs()) + .setIndexRestorationLatencyMillis(fromNativeStats.getIndexRestorationLatencyMs()) + .setOriginalDocumentCount(fromNativeStats.getNumOriginalDocuments()) + .setDeletedDocumentCount(fromNativeStats.getNumDeletedDocuments()) + .setExpiredDocumentCount(fromNativeStats.getNumExpiredDocuments()) + .setStorageSizeBeforeBytes(fromNativeStats.getStorageSizeBefore()) + .setStorageSizeAfterBytes(fromNativeStats.getStorageSizeAfter()) + .setTimeSinceLastOptimizeMillis(fromNativeStats.getTimeSinceLastOptimizeMs()); + } } diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/OptimizeStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/OptimizeStats.java new file mode 100644 index 000000000000..83bd50f92e3b --- /dev/null +++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/OptimizeStats.java @@ -0,0 +1,243 @@ +/* + * Copyright 2021 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.external.localstorage.stats; + +import android.annotation.NonNull; +import android.app.appsearch.AppSearchResult; + +import java.util.Objects; + +/** + * Class holds detailed stats for Optimize. + * + * @hide + */ +public final class OptimizeStats { + /** + * The status code returned by {@link AppSearchResult#getResultCode()} for the call or internal + * state. + */ + @AppSearchResult.ResultCode private final int mStatusCode; + + private final int mTotalLatencyMillis; + private final int mNativeLatencyMillis; + + // Time used to optimize the document store in millis. + private final int mNativeDocumentStoreOptimizeLatencyMillis; + + // Time used to restore the index in millis. + private final int mNativeIndexRestorationLatencyMillis; + + // Number of documents before the optimization. + private final int mNativeOriginalDocumentCount; + + // Number of documents deleted during the optimization. + private final int mNativeDeletedDocumentCount; + + // Number of documents expired during the optimization. + private final int mNativeExpiredDocumentCount; + + // Size of storage in bytes before the optimization. + private final long mNativeStorageSizeBeforeBytes; + + // Size of storage in bytes after the optimization. + private final long mNativeStorageSizeAfterBytes; + + // The amount of time in millis since the last optimization ran calculated using wall clock time + private final long mNativeTimeSinceLastOptimizeMillis; + + OptimizeStats(@NonNull Builder builder) { + Objects.requireNonNull(builder); + mStatusCode = builder.mStatusCode; + mTotalLatencyMillis = builder.mTotalLatencyMillis; + mNativeLatencyMillis = builder.mNativeLatencyMillis; + mNativeDocumentStoreOptimizeLatencyMillis = + builder.mNativeDocumentStoreOptimizeLatencyMillis; + mNativeIndexRestorationLatencyMillis = builder.mNativeIndexRestorationLatencyMillis; + mNativeOriginalDocumentCount = builder.mNativeOriginalDocumentCount; + mNativeDeletedDocumentCount = builder.mNativeDeletedDocumentCount; + mNativeExpiredDocumentCount = builder.mNativeExpiredDocumentCount; + mNativeStorageSizeBeforeBytes = builder.mNativeStorageSizeBeforeBytes; + mNativeStorageSizeAfterBytes = builder.mNativeStorageSizeAfterBytes; + mNativeTimeSinceLastOptimizeMillis = builder.mNativeTimeSinceLastOptimizeMillis; + } + + /** Returns status code for this optimization. */ + @AppSearchResult.ResultCode + public int getStatusCode() { + return mStatusCode; + } + + /** Returns total latency of this optimization in millis. */ + public int getTotalLatencyMillis() { + return mTotalLatencyMillis; + } + + /** Returns how much time in millis spent in the native code. */ + public int getNativeLatencyMillis() { + return mNativeLatencyMillis; + } + + /** Returns time used to optimize the document store in millis. */ + public int getDocumentStoreOptimizeLatencyMillis() { + return mNativeDocumentStoreOptimizeLatencyMillis; + } + + /** Returns time used to restore the index in millis. */ + public int getIndexRestorationLatencyMillis() { + return mNativeIndexRestorationLatencyMillis; + } + + /** Returns number of documents before the optimization. */ + public int getOriginalDocumentCount() { + return mNativeOriginalDocumentCount; + } + + /** Returns number of documents deleted during the optimization. */ + public int getDeletedDocumentCount() { + return mNativeDeletedDocumentCount; + } + + /** Returns number of documents expired during the optimization. */ + public int getExpiredDocumentCount() { + return mNativeExpiredDocumentCount; + } + + /** Returns size of storage in bytes before the optimization. */ + public long getStorageSizeBeforeBytes() { + return mNativeStorageSizeBeforeBytes; + } + + /** Returns size of storage in bytes after the optimization. */ + public long getStorageSizeAfterBytes() { + return mNativeStorageSizeAfterBytes; + } + + /** + * Returns the amount of time in millis since the last optimization ran calculated using wall + * clock time. + */ + public long getTimeSinceLastOptimizeMillis() { + return mNativeTimeSinceLastOptimizeMillis; + } + + /** Builder for {@link RemoveStats}. */ + public static class Builder { + /** + * The status code returned by {@link AppSearchResult#getResultCode()} for the call or + * internal state. + */ + @AppSearchResult.ResultCode int mStatusCode; + + int mTotalLatencyMillis; + int mNativeLatencyMillis; + int mNativeDocumentStoreOptimizeLatencyMillis; + int mNativeIndexRestorationLatencyMillis; + int mNativeOriginalDocumentCount; + int mNativeDeletedDocumentCount; + int mNativeExpiredDocumentCount; + long mNativeStorageSizeBeforeBytes; + long mNativeStorageSizeAfterBytes; + long mNativeTimeSinceLastOptimizeMillis; + + /** Sets the status code. */ + @NonNull + public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) { + mStatusCode = statusCode; + return this; + } + + /** Sets total latency in millis. */ + @NonNull + public Builder setTotalLatencyMillis(int totalLatencyMillis) { + mTotalLatencyMillis = totalLatencyMillis; + return this; + } + + /** Sets native latency in millis. */ + @NonNull + public Builder setNativeLatencyMillis(int nativeLatencyMillis) { + mNativeLatencyMillis = nativeLatencyMillis; + return this; + } + + /** Sets time used to optimize the document store. */ + @NonNull + public Builder setDocumentStoreOptimizeLatencyMillis( + int documentStoreOptimizeLatencyMillis) { + mNativeDocumentStoreOptimizeLatencyMillis = documentStoreOptimizeLatencyMillis; + return this; + } + + /** Sets time used to restore the index. */ + @NonNull + public Builder setIndexRestorationLatencyMillis(int indexRestorationLatencyMillis) { + mNativeIndexRestorationLatencyMillis = indexRestorationLatencyMillis; + return this; + } + + /** Sets number of documents before the optimization. */ + @NonNull + public Builder setOriginalDocumentCount(int originalDocumentCount) { + mNativeOriginalDocumentCount = originalDocumentCount; + return this; + } + + /** Sets number of documents deleted during the optimization. */ + @NonNull + public Builder setDeletedDocumentCount(int deletedDocumentCount) { + mNativeDeletedDocumentCount = deletedDocumentCount; + return this; + } + + /** Sets number of documents expired during the optimization. */ + @NonNull + public Builder setExpiredDocumentCount(int expiredDocumentCount) { + mNativeExpiredDocumentCount = expiredDocumentCount; + return this; + } + + /** Sets Storage size in bytes before optimization. */ + @NonNull + public Builder setStorageSizeBeforeBytes(long storageSizeBeforeBytes) { + mNativeStorageSizeBeforeBytes = storageSizeBeforeBytes; + return this; + } + + /** Sets storage size in bytes after optimization. */ + @NonNull + public Builder setStorageSizeAfterBytes(long storageSizeAfterBytes) { + mNativeStorageSizeAfterBytes = storageSizeAfterBytes; + return this; + } + + /** + * Sets the amount the time since the last optimize ran calculated using wall clock time. + */ + @NonNull + public Builder setTimeSinceLastOptimizeMillis(long timeSinceLastOptimizeMillis) { + mNativeTimeSinceLastOptimizeMillis = timeSinceLastOptimizeMillis; + return this; + } + + /** Creates a {@link OptimizeStats}. */ + @NonNull + public OptimizeStats build() { + return new OptimizeStats(/* builder= */ this); + } + } +} diff --git a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java index 2cbce106932d..fdf6a008b10c 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java @@ -32,6 +32,7 @@ import com.android.server.appsearch.AppSearchConfig; import com.android.server.appsearch.external.localstorage.AppSearchLogger; import com.android.server.appsearch.external.localstorage.stats.CallStats; import com.android.server.appsearch.external.localstorage.stats.InitializeStats; +import com.android.server.appsearch.external.localstorage.stats.OptimizeStats; import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats; import com.android.server.appsearch.external.localstorage.stats.RemoveStats; import com.android.server.appsearch.external.localstorage.stats.SearchStats; @@ -145,7 +146,7 @@ public final class PlatformLogger implements AppSearchLogger { } @Override - public void logStats(@NonNull InitializeStats stats) throws AppSearchException { + public void logStats(@NonNull InitializeStats stats) { Objects.requireNonNull(stats); synchronized (mLock) { if (shouldLogForTypeLocked(CallStats.CALL_TYPE_INITIALIZE)) { @@ -155,7 +156,7 @@ public final class PlatformLogger implements AppSearchLogger { } @Override - public void logStats(@NonNull SearchStats stats) throws AppSearchException { + public void logStats(@NonNull SearchStats stats) { Objects.requireNonNull(stats); synchronized (mLock) { if (shouldLogForTypeLocked(CallStats.CALL_TYPE_SEARCH)) { @@ -165,10 +166,20 @@ public final class PlatformLogger implements AppSearchLogger { } @Override - public void logStats(@NonNull RemoveStats stats) throws AppSearchException { + public void logStats(@NonNull RemoveStats stats) { // TODO(b/173532925): Log stats } + @Override + public void logStats(@NonNull OptimizeStats stats) { + Objects.requireNonNull(stats); + synchronized (mLock) { + if (shouldLogForTypeLocked(CallStats.CALL_TYPE_OPTIMIZE)) { + logStatsImplLocked(stats); + } + } + } + /** * Removes cached UID for package. * @@ -326,6 +337,27 @@ public final class PlatformLogger implements AppSearchLogger { stats.getResetStatusCode()); } + @GuardedBy("mLock") + private void logStatsImplLocked(@NonNull OptimizeStats stats) { + mLastPushTimeMillisLocked = SystemClock.elapsedRealtime(); + ExtraStats extraStats = createExtraStatsLocked(/*packageName=*/ null, + CallStats.CALL_TYPE_OPTIMIZE); + AppSearchStatsLog.write(AppSearchStatsLog.APP_SEARCH_OPTIMIZE_STATS_REPORTED, + extraStats.mSamplingInterval, + extraStats.mSkippedSampleCount, + stats.getStatusCode(), + stats.getTotalLatencyMillis(), + stats.getNativeLatencyMillis(), + stats.getDocumentStoreOptimizeLatencyMillis(), + stats.getIndexRestorationLatencyMillis(), + stats.getOriginalDocumentCount(), + stats.getDeletedDocumentCount(), + stats.getExpiredDocumentCount(), + stats.getStorageSizeBeforeBytes(), + stats.getStorageSizeAfterBytes(), + stats.getTimeSinceLastOptimizeMillis()); + } + /** * Calculate the hash code as an integer by returning the last four bytes of its MD5. * @@ -464,15 +496,19 @@ public final class PlatformLogger implements AppSearchLogger { return mConfig.getCachedSamplingIntervalForBatchCallStats(); case CallStats.CALL_TYPE_PUT_DOCUMENT: return mConfig.getCachedSamplingIntervalForPutDocumentStats(); - case CallStats.CALL_TYPE_UNKNOWN: case CallStats.CALL_TYPE_INITIALIZE: + return mConfig.getCachedSamplingIntervalForInitializeStats(); + case CallStats.CALL_TYPE_SEARCH: + return mConfig.getCachedSamplingIntervalForSearchStats(); + case CallStats.CALL_TYPE_GLOBAL_SEARCH: + return mConfig.getCachedSamplingIntervalForGlobalSearchStats(); + case CallStats.CALL_TYPE_OPTIMIZE: + return mConfig.getCachedSamplingIntervalForOptimizeStats(); + case CallStats.CALL_TYPE_UNKNOWN: case CallStats.CALL_TYPE_SET_SCHEMA: case CallStats.CALL_TYPE_GET_DOCUMENT: case CallStats.CALL_TYPE_REMOVE_DOCUMENT_BY_ID: - case CallStats.CALL_TYPE_SEARCH: - case CallStats.CALL_TYPE_OPTIMIZE: case CallStats.CALL_TYPE_FLUSH: - case CallStats.CALL_TYPE_GLOBAL_SEARCH: case CallStats.CALL_TYPE_REMOVE_DOCUMENT_BY_SEARCH: // TODO(b/173532925) Some of them above will have dedicated sampling ratio config default: diff --git a/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java b/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java index 8336663d4dd1..9926953f110f 100644 --- a/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/appsearch/AppSearchConfigTest.java @@ -50,6 +50,14 @@ public class AppSearchConfigTest { AppSearchConfig.DEFAULT_SAMPLING_INTERVAL); assertThat(appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()).isEqualTo( AppSearchConfig.DEFAULT_SAMPLING_INTERVAL); + assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo( + AppSearchConfig.DEFAULT_SAMPLING_INTERVAL); + assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo( + AppSearchConfig.DEFAULT_SAMPLING_INTERVAL); + assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo( + AppSearchConfig.DEFAULT_SAMPLING_INTERVAL); + assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo( + AppSearchConfig.DEFAULT_SAMPLING_INTERVAL); assertThat(appSearchConfig.getCachedLimitConfigMaxDocumentSizeBytes()).isEqualTo( AppSearchConfig.DEFAULT_LIMIT_CONFIG_MAX_DOCUMENT_SIZE_BYTES); assertThat(appSearchConfig.getCachedLimitConfigMaxDocumentCount()).isEqualTo( @@ -100,6 +108,11 @@ public class AppSearchConfigTest { final int samplingIntervalDefault = -1; final int samplingIntervalPutDocumentStats = -2; final int samplingIntervalBatchCallStats = -3; + final int samplingIntervalInitializeStats = -4; + final int samplingIntervalSearchStats = -5; + final int samplingIntervalGlobalSearchStats = -6; + final int samplingIntervalOptimizeStats = -7; + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT, Integer.toString(samplingIntervalDefault), @@ -112,6 +125,22 @@ public class AppSearchConfigTest { AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS, Integer.toString(samplingIntervalBatchCallStats), false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS, + Integer.toString(samplingIntervalInitializeStats), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS, + Integer.toString(samplingIntervalSearchStats), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS, + Integer.toString(samplingIntervalGlobalSearchStats), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS, + Integer.toString(samplingIntervalOptimizeStats), + false); AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR); @@ -121,6 +150,14 @@ public class AppSearchConfigTest { samplingIntervalPutDocumentStats); assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo( samplingIntervalBatchCallStats); + assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo( + samplingIntervalInitializeStats); + assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo( + samplingIntervalSearchStats); + assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo( + samplingIntervalGlobalSearchStats); + assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo( + samplingIntervalOptimizeStats); } @Test @@ -128,6 +165,10 @@ public class AppSearchConfigTest { int samplingIntervalDefault = -1; int samplingIntervalPutDocumentStats = -2; int samplingIntervalBatchCallStats = -3; + int samplingIntervalInitializeStats = -4; + int samplingIntervalSearchStats = -5; + int samplingIntervalGlobalSearchStats = -6; + int samplingIntervalOptimizeStats = -7; DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT, Integer.toString(samplingIntervalDefault), @@ -140,12 +181,32 @@ public class AppSearchConfigTest { AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS, Integer.toString(samplingIntervalBatchCallStats), false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS, + Integer.toString(samplingIntervalInitializeStats), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS, + Integer.toString(samplingIntervalSearchStats), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS, + Integer.toString(samplingIntervalGlobalSearchStats), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS, + Integer.toString(samplingIntervalOptimizeStats), + false); AppSearchConfig appSearchConfig = AppSearchConfig.create(DIRECT_EXECUTOR); // Overrides samplingIntervalDefault = -4; samplingIntervalPutDocumentStats = -5; samplingIntervalBatchCallStats = -6; + samplingIntervalInitializeStats = -7; + samplingIntervalSearchStats = -8; + samplingIntervalGlobalSearchStats = -9; + samplingIntervalOptimizeStats = -10; DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, AppSearchConfig.KEY_SAMPLING_INTERVAL_DEFAULT, Integer.toString(samplingIntervalDefault), @@ -158,6 +219,22 @@ public class AppSearchConfigTest { AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_BATCH_CALL_STATS, Integer.toString(samplingIntervalBatchCallStats), false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_INITIALIZE_STATS, + Integer.toString(samplingIntervalInitializeStats), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_SEARCH_STATS, + Integer.toString(samplingIntervalSearchStats), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_GLOBAL_SEARCH_STATS, + Integer.toString(samplingIntervalGlobalSearchStats), + false); + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_APPSEARCH, + AppSearchConfig.KEY_SAMPLING_INTERVAL_FOR_OPTIMIZE_STATS, + Integer.toString(samplingIntervalOptimizeStats), + false); assertThat(appSearchConfig.getCachedSamplingIntervalDefault()).isEqualTo( samplingIntervalDefault); @@ -165,6 +242,14 @@ public class AppSearchConfigTest { samplingIntervalPutDocumentStats); assertThat(appSearchConfig.getCachedSamplingIntervalForBatchCallStats()).isEqualTo( samplingIntervalBatchCallStats); + assertThat(appSearchConfig.getCachedSamplingIntervalForInitializeStats()).isEqualTo( + samplingIntervalInitializeStats); + assertThat(appSearchConfig.getCachedSamplingIntervalForSearchStats()).isEqualTo( + samplingIntervalSearchStats); + assertThat(appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()).isEqualTo( + samplingIntervalGlobalSearchStats); + assertThat(appSearchConfig.getCachedSamplingIntervalForOptimizeStats()).isEqualTo( + samplingIntervalOptimizeStats); } /** @@ -364,6 +449,18 @@ public class AppSearchConfigTest { Assert.assertThrows("Trying to use a closed AppSearchConfig instance.", IllegalStateException.class, () -> appSearchConfig.getCachedSamplingIntervalForPutDocumentStats()); + Assert.assertThrows("Trying to use a closed AppSearchConfig instance.", + IllegalStateException.class, + () -> appSearchConfig.getCachedSamplingIntervalForInitializeStats()); + Assert.assertThrows("Trying to use a closed AppSearchConfig instance.", + IllegalStateException.class, + () -> appSearchConfig.getCachedSamplingIntervalForSearchStats()); + Assert.assertThrows("Trying to use a closed AppSearchConfig instance.", + IllegalStateException.class, + () -> appSearchConfig.getCachedSamplingIntervalForGlobalSearchStats()); + Assert.assertThrows("Trying to use a closed AppSearchConfig instance.", + IllegalStateException.class, + () -> appSearchConfig.getCachedSamplingIntervalForOptimizeStats()); Assert.assertThrows("Trying to use a closed AppSearchConfig instance.", IllegalStateException.class, () -> appSearchConfig.getCachedBytesOptimizeThreshold()); diff --git a/services/tests/mockingservicestests/src/com/android/server/appsearch/OWNERS b/services/tests/mockingservicestests/src/com/android/server/appsearch/OWNERS new file mode 100644 index 000000000000..24f6b0b6b2b6 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/appsearch/OWNERS @@ -0,0 +1 @@ +include /apex/appsearch/OWNERS \ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java index 5b067bc58da3..f40a5ad7bcb6 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java @@ -42,6 +42,7 @@ import androidx.test.core.app.ApplicationProvider; import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter; import com.android.server.appsearch.external.localstorage.stats.InitializeStats; +import com.android.server.appsearch.external.localstorage.stats.OptimizeStats; import com.android.server.appsearch.external.localstorage.util.PrefixUtil; import com.android.server.appsearch.icing.proto.DocumentProto; import com.android.server.appsearch.icing.proto.GetOptimizeInfoResultProto; @@ -451,19 +452,26 @@ public class AppSearchImplTest { assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(1); // Increase mutation counter and stop before reach the threshold - mAppSearchImpl.checkForOptimize(AppSearchImpl.CHECK_OPTIMIZE_INTERVAL - 1); + mAppSearchImpl.checkForOptimize( + AppSearchImpl.CHECK_OPTIMIZE_INTERVAL - 1, /*builder=*/ null); // Verify the optimize() isn't triggered. optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked(); assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(1); // Increase the counter and reach the threshold, optimize() should be triggered. - mAppSearchImpl.checkForOptimize(/*mutateBatchSize=*/ 1); + OptimizeStats.Builder builder = new OptimizeStats.Builder(); + mAppSearchImpl.checkForOptimize(/*mutateBatchSize=*/ 1, builder); // Verify optimize() is triggered. optimizeInfo = mAppSearchImpl.getOptimizeInfoResultLocked(); assertThat(optimizeInfo.getOptimizableDocs()).isEqualTo(0); assertThat(optimizeInfo.getEstimatedOptimizableBytes()).isEqualTo(0); + + // Verify the stats have been set. + OptimizeStats oStats = builder.build(); + assertThat(oStats.getOriginalDocumentCount()).isEqualTo(1); + assertThat(oStats.getDeletedDocumentCount()).isEqualTo(1); } @Test diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java index 7bacbb63f10c..7c976876a731 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java @@ -29,12 +29,14 @@ import android.app.appsearch.exceptions.AppSearchException; import com.android.server.appsearch.external.localstorage.stats.CallStats; import com.android.server.appsearch.external.localstorage.stats.InitializeStats; +import com.android.server.appsearch.external.localstorage.stats.OptimizeStats; import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats; import com.android.server.appsearch.external.localstorage.stats.RemoveStats; import com.android.server.appsearch.external.localstorage.stats.SearchStats; import com.android.server.appsearch.icing.proto.DeleteStatsProto; import com.android.server.appsearch.icing.proto.DocumentProto; import com.android.server.appsearch.icing.proto.InitializeStatsProto; +import com.android.server.appsearch.icing.proto.OptimizeStatsProto; import com.android.server.appsearch.icing.proto.PutDocumentStatsProto; import com.android.server.appsearch.icing.proto.PutResultProto; import com.android.server.appsearch.icing.proto.QueryStatsProto; @@ -81,6 +83,7 @@ public class AppSearchLoggerTest { @Nullable InitializeStats mInitializeStats; @Nullable SearchStats mSearchStats; @Nullable RemoveStats mRemoveStats; + @Nullable OptimizeStats mOptimizeStats; @Override public void logStats(@NonNull CallStats stats) { @@ -106,6 +109,11 @@ public class AppSearchLoggerTest { public void logStats(@NonNull RemoveStats stats) { mRemoveStats = stats; } + + @Override + public void logStats(@NonNull OptimizeStats stats) { + mOptimizeStats = stats; + } } @Test @@ -286,6 +294,48 @@ public class AppSearchLoggerTest { assertThat(rStats.getDeletedDocumentCount()).isEqualTo(nativeNumDocumentDeleted); } + @Test + public void testAppSearchLoggerHelper_testCopyNativeStats_optimize() { + int nativeLatencyMillis = 1; + int nativeDocumentStoreOptimizeLatencyMillis = 2; + int nativeIndexRestorationLatencyMillis = 3; + int nativeNumOriginalDocuments = 4; + int nativeNumDeletedDocuments = 5; + int nativeNumExpiredDocuments = 6; + long nativeStorageSizeBeforeBytes = Integer.MAX_VALUE + 1; + long nativeStorageSizeAfterBytes = Integer.MAX_VALUE + 2; + long nativeTimeSinceLastOptimizeMillis = Integer.MAX_VALUE + 3; + OptimizeStatsProto optimizeStatsProto = + OptimizeStatsProto.newBuilder() + .setLatencyMs(nativeLatencyMillis) + .setDocumentStoreOptimizeLatencyMs(nativeDocumentStoreOptimizeLatencyMillis) + .setIndexRestorationLatencyMs(nativeIndexRestorationLatencyMillis) + .setNumOriginalDocuments(nativeNumOriginalDocuments) + .setNumDeletedDocuments(nativeNumDeletedDocuments) + .setNumExpiredDocuments(nativeNumExpiredDocuments) + .setStorageSizeBefore(nativeStorageSizeBeforeBytes) + .setStorageSizeAfter(nativeStorageSizeAfterBytes) + .setTimeSinceLastOptimizeMs(nativeTimeSinceLastOptimizeMillis) + .build(); + OptimizeStats.Builder oBuilder = new OptimizeStats.Builder(); + + AppSearchLoggerHelper.copyNativeStats(optimizeStatsProto, oBuilder); + + OptimizeStats oStats = oBuilder.build(); + assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis); + assertThat(oStats.getDocumentStoreOptimizeLatencyMillis()) + .isEqualTo(nativeDocumentStoreOptimizeLatencyMillis); + assertThat(oStats.getIndexRestorationLatencyMillis()) + .isEqualTo(nativeIndexRestorationLatencyMillis); + assertThat(oStats.getOriginalDocumentCount()).isEqualTo(nativeNumOriginalDocuments); + assertThat(oStats.getDeletedDocumentCount()).isEqualTo(nativeNumDeletedDocuments); + assertThat(oStats.getExpiredDocumentCount()).isEqualTo(nativeNumExpiredDocuments); + assertThat(oStats.getStorageSizeBeforeBytes()).isEqualTo(nativeStorageSizeBeforeBytes); + assertThat(oStats.getStorageSizeAfterBytes()).isEqualTo(nativeStorageSizeAfterBytes); + assertThat(oStats.getTimeSinceLastOptimizeMillis()) + .isEqualTo(nativeTimeSinceLastOptimizeMillis); + } + // // Testing actual logging // diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java index 57d994155d5b..c1dc0e447c70 100644 --- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java +++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java @@ -348,4 +348,49 @@ public class AppSearchStatsTest { assertThat(rStats.getDeleteType()).isEqualTo(deleteType); assertThat(rStats.getDeletedDocumentCount()).isEqualTo(documentDeletedCount); } + + @Test + public void testAppSearchStats_OptimizeStats() { + int nativeLatencyMillis = 1; + int nativeDocumentStoreOptimizeLatencyMillis = 2; + int nativeIndexRestorationLatencyMillis = 3; + int nativeNumOriginalDocuments = 4; + int nativeNumDeletedDocuments = 5; + int nativeNumExpiredDocuments = 6; + long nativeStorageSizeBeforeBytes = Integer.MAX_VALUE + 1; + long nativeStorageSizeAfterBytes = Integer.MAX_VALUE + 2; + long nativeTimeSinceLastOptimizeMillis = Integer.MAX_VALUE + 3; + + final OptimizeStats oStats = + new OptimizeStats.Builder() + .setStatusCode(TEST_STATUS_CODE) + .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS) + .setNativeLatencyMillis(nativeLatencyMillis) + .setDocumentStoreOptimizeLatencyMillis( + nativeDocumentStoreOptimizeLatencyMillis) + .setIndexRestorationLatencyMillis(nativeIndexRestorationLatencyMillis) + .setOriginalDocumentCount(nativeNumOriginalDocuments) + .setDeletedDocumentCount(nativeNumDeletedDocuments) + .setExpiredDocumentCount(nativeNumExpiredDocuments) + .setStorageSizeBeforeBytes(nativeStorageSizeBeforeBytes) + .setStorageSizeAfterBytes(nativeStorageSizeAfterBytes) + .setTimeSinceLastOptimizeMillis(nativeTimeSinceLastOptimizeMillis) + .build(); + + assertThat(oStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE); + assertThat(oStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS); + assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis); + assertThat(oStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis); + assertThat(oStats.getDocumentStoreOptimizeLatencyMillis()) + .isEqualTo(nativeDocumentStoreOptimizeLatencyMillis); + assertThat(oStats.getIndexRestorationLatencyMillis()) + .isEqualTo(nativeIndexRestorationLatencyMillis); + assertThat(oStats.getOriginalDocumentCount()).isEqualTo(nativeNumOriginalDocuments); + assertThat(oStats.getDeletedDocumentCount()).isEqualTo(nativeNumDeletedDocuments); + assertThat(oStats.getExpiredDocumentCount()).isEqualTo(nativeNumExpiredDocuments); + assertThat(oStats.getStorageSizeBeforeBytes()).isEqualTo(nativeStorageSizeBeforeBytes); + assertThat(oStats.getStorageSizeAfterBytes()).isEqualTo(nativeStorageSizeAfterBytes); + assertThat(oStats.getTimeSinceLastOptimizeMillis()) + .isEqualTo(nativeTimeSinceLastOptimizeMillis); + } }