summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Dorokhine <adorokhine@google.com>2021-04-28 03:33:15 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2021-04-28 03:33:15 +0000
commit5d3d644cbc3da2b8e92f4b95f3dc481f1ea31ed9 (patch)
tree50ab0ec633e79d88a3586d8bff2633cd2c47f175
parente19e70840804fae39039b47c368db23b92150af9 (diff)
parent1b690b4540de43989d180d228e9994460a46a034 (diff)
Merge "Update framework from jetpack." into sc-dev
-rw-r--r--apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java19
-rw-r--r--apex/appsearch/framework/java/external/android/app/appsearch/exceptions/AppSearchException.java7
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java9
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java3
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java166
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLogger.java8
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchLoggerHelper.java66
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/InitializeStats.java404
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SearchStats.java460
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java12
-rw-r--r--apex/appsearch/synced_jetpack_changeid.txt2
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java77
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java218
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/stats/AppSearchStatsTest.java131
16 files changed, 1547 insertions, 59 deletions
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
index 8a162d49e151..b7bd3878d4fa 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaResponse.java
@@ -96,8 +96,13 @@ public class SetSchemaResponse {
}
/**
- * Returns a {@link Set} of schema type that were deleted by the {@link
- * AppSearchSession#setSchema} call.
+ * Returns a {@link Set} of deleted schema types.
+ *
+ * <p>A "deleted" type is a schema type that was previously a part of the database schema but
+ * was not present in the {@link SetSchemaRequest} object provided in the
+ * {@link AppSearchSession#setSchema) call.
+ *
+ * <p>Documents for a deleted type are removed from the database.
*/
@NonNull
public Set<String> getDeletedTypes() {
@@ -113,6 +118,15 @@ public class SetSchemaResponse {
/**
* Returns a {@link Set} of schema type that were migrated by the {@link
* AppSearchSession#setSchema} call.
+ *
+ * <p>A "migrated" type is a schema type that has triggered a {@link Migrator} instance to
+ * migrate documents of the schema type to another schema type, or to another version of the
+ * schema type.
+ *
+ * <p>If a document fails to be migrated, a {@link MigrationFailure} will be generated for that
+ * document.
+ *
+ * @see Migrator
*/
@NonNull
public Set<String> getMigratedTypes() {
@@ -132,6 +146,7 @@ public class SetSchemaResponse {
* <p>If a {@link Migrator} is provided for this type and the migration is success triggered.
* The type will also appear in {@link #getMigratedTypes()}.
*
+ * @see SetSchemaRequest
* @see AppSearchSession#setSchema
* @see SetSchemaRequest.Builder#setForceOverride
*/
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/exceptions/AppSearchException.java b/apex/appsearch/framework/java/external/android/app/appsearch/exceptions/AppSearchException.java
index ca4ea2bfd3bb..62593ae8fc29 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/exceptions/AppSearchException.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/exceptions/AppSearchException.java
@@ -42,6 +42,8 @@ public class AppSearchException extends Exception {
* Initializes an {@link AppSearchException} with a result code and message.
*
* @param resultCode One of the constants documented in {@link AppSearchResult#getResultCode}.
+ * @param message The detail message (which is saved for later retrieval by the {@link
+ * #getMessage()} method).
*/
public AppSearchException(
@AppSearchResult.ResultCode int resultCode, @Nullable String message) {
@@ -52,6 +54,11 @@ public class AppSearchException extends Exception {
* Initializes an {@link AppSearchException} with a result code, message and cause.
*
* @param resultCode One of the constants documented in {@link AppSearchResult#getResultCode}.
+ * @param message The detail message (which is saved for later retrieval by the {@link
+ * #getMessage()} method).
+ * @param cause The cause (which is saved for later retrieval by the {@link #getCause()}
+ * method). (A null value is permitted, and indicates that the cause is nonexistent or
+ * unknown.)
*/
public AppSearchException(
@AppSearchResult.ResultCode int resultCode,
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 3f6e8a5a7906..a4188a2733b8 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -501,7 +501,8 @@ public class AppSearchManagerService extends SystemService {
packageName,
databaseName,
queryExpression,
- new SearchSpec(searchSpecBundle));
+ new SearchSpec(searchSpecBundle),
+ /*logger=*/ null);
invokeCallbackOnResult(
callback,
AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
@@ -535,7 +536,8 @@ public class AppSearchManagerService extends SystemService {
queryExpression,
new SearchSpec(searchSpecBundle),
packageName,
- callingUid);
+ callingUid,
+ /*logger=*/ null);
invokeCallbackOnResult(
callback,
AppSearchResult.newSuccessfulResult(searchResultPage.getBundle()));
@@ -609,7 +611,8 @@ public class AppSearchManagerService extends SystemService {
packageName,
databaseName,
queryExpression,
- new SearchSpec(searchSpecBundle));
+ new SearchSpec(searchSpecBundle),
+ /*logger=*/ null);
while (!searchResultPage.getResults().isEmpty()) {
for (int i = 0; i < searchResultPage.getResults().size(); i++) {
AppSearchMigrationHelper.writeBundleToOutputStream(
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
index 45023f966ad2..94ee830f8e74 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
@@ -149,7 +149,8 @@ public final class ImplInstanceManager {
private AppSearchImpl createImpl(@NonNull Context context, @UserIdInt int userId)
throws AppSearchException {
File appSearchDir = getAppSearchDir(userId);
- return AppSearchImpl.create(appSearchDir, context, userId, mGlobalQuerierPackage);
+ return AppSearchImpl.create(
+ appSearchDir, context, userId, mGlobalQuerierPackage, /*logger=*/ null);
}
/**
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 98fcb1370d8b..e5e20e733264 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
@@ -54,7 +54,9 @@ import com.android.server.appsearch.external.localstorage.converter.SearchResult
import com.android.server.appsearch.external.localstorage.converter.SearchSpecToProtoConverter;
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.PutDocumentStats;
+import com.android.server.appsearch.external.localstorage.stats.SearchStats;
import com.google.android.icing.IcingSearchEngine;
import com.google.android.icing.proto.DeleteByQueryResultProto;
@@ -178,28 +180,63 @@ public final class AppSearchImpl implements Closeable {
/**
* Creates and initializes an instance of {@link AppSearchImpl} which writes data to the given
* folder.
+ *
+ * <p>Clients can pass a {@link AppSearchLogger} here through their AppSearchSession, but it
+ * can't be saved inside {@link AppSearchImpl}, because the impl will be shared by all the
+ * sessions for the same package in JetPack.
+ *
+ * <p>Instead, logger instance needs to be passed to each individual method, like create, query
+ * and putDocument.
+ *
+ * @param logger collects stats for initialization if provided.
*/
@NonNull
public static AppSearchImpl create(
@NonNull File icingDir,
@NonNull Context context,
int userId,
- @NonNull String globalQuerierPackage)
+ @NonNull String globalQuerierPackage,
+ @Nullable AppSearchLogger logger)
throws AppSearchException {
Objects.requireNonNull(icingDir);
Objects.requireNonNull(context);
Objects.requireNonNull(globalQuerierPackage);
+
+ long totalLatencyStartMillis = SystemClock.elapsedRealtime();
+ InitializeStats.Builder initStatsBuilder = null;
+ if (logger != null) {
+ initStatsBuilder = new InitializeStats.Builder();
+ }
+
AppSearchImpl appSearchImpl =
- new AppSearchImpl(icingDir, context, userId, globalQuerierPackage);
+ new AppSearchImpl(
+ icingDir, context, userId, globalQuerierPackage, initStatsBuilder);
+
+ long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime();
appSearchImpl.initializeVisibilityStore();
+ long prepareVisibilityStoreLatencyEndMillis = SystemClock.elapsedRealtime();
+
+ if (logger != null && initStatsBuilder != null) {
+ initStatsBuilder
+ .setTotalLatencyMillis(
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis))
+ .setPrepareVisibilityStoreLatencyMillis(
+ (int)
+ (prepareVisibilityStoreLatencyEndMillis
+ - prepareVisibilityStoreLatencyStartMillis));
+ logger.logStats(initStatsBuilder.build());
+ }
+
return appSearchImpl;
}
+ /** @param initStatsBuilder collects stats for initialization if provided. */
private AppSearchImpl(
@NonNull File icingDir,
@NonNull Context context,
int userId,
- @NonNull String globalQuerierPackage)
+ @NonNull String globalQuerierPackage,
+ @Nullable InitializeStats.Builder initStatsBuilder)
throws AppSearchException {
mReadWriteLock.writeLock().lock();
@@ -211,13 +248,24 @@ public final class AppSearchImpl implements Closeable {
.setBaseDir(icingDir.getAbsolutePath())
.build();
mIcingSearchEngineLocked = new IcingSearchEngine(options);
-
mVisibilityStoreLocked =
new VisibilityStore(this, context, userId, globalQuerierPackage);
-
InitializeResultProto initializeResultProto = mIcingSearchEngineLocked.initialize();
+
+ if (initStatsBuilder != null) {
+ initStatsBuilder
+ .setStatusCode(
+ statusProtoToAppSearchException(initializeResultProto.getStatus())
+ .getResultCode())
+ // TODO(b/173532925) how to get DeSyncs value
+ .setHasDeSync(false);
+ AppSearchLoggerHelper.copyNativeStats(
+ initializeResultProto.getInitializeStats(), initStatsBuilder);
+ }
+
+ long prepareSchemaAndNamespacesLatencyStartMillis = SystemClock.elapsedRealtime();
SchemaProto schemaProto;
- GetAllNamespacesResultProto getAllNamespacesResultProto;
+ GetAllNamespacesResultProto getAllNamespacesResultProto = null;
try {
checkSuccess(initializeResultProto.getStatus());
schemaProto = getSchemaProtoLocked();
@@ -225,6 +273,17 @@ public final class AppSearchImpl implements Closeable {
checkSuccess(getAllNamespacesResultProto.getStatus());
} catch (AppSearchException e) {
Log.w(TAG, "Error initializing, resetting IcingSearchEngine.", e);
+ if (initStatsBuilder != null && getAllNamespacesResultProto != null) {
+ initStatsBuilder
+ .setStatusCode(
+ statusProtoToAppSearchException(
+ getAllNamespacesResultProto.getStatus())
+ .getResultCode())
+ .setPrepareSchemaAndNamespacesLatencyMillis(
+ (int)
+ (SystemClock.elapsedRealtime()
+ - prepareSchemaAndNamespacesLatencyStartMillis));
+ }
// Some error. Reset and see if it fixes it.
resetLocked();
return;
@@ -240,6 +299,14 @@ public final class AppSearchImpl implements Closeable {
for (String prefixedNamespace : getAllNamespacesResultProto.getNamespacesList()) {
addToMap(mNamespaceMapLocked, getPrefix(prefixedNamespace), prefixedNamespace);
}
+
+ // logging prepare_schema_and_namespaces latency
+ if (initStatsBuilder != null) {
+ initStatsBuilder.setPrepareSchemaAndNamespacesLatencyMillis(
+ (int)
+ (SystemClock.elapsedRealtime()
+ - prepareSchemaAndNamespacesLatencyStartMillis));
+ }
} finally {
mReadWriteLock.writeLock().unlock();
}
@@ -539,7 +606,7 @@ public final class AppSearchImpl implements Closeable {
addToMap(mNamespaceMapLocked, prefix, documentBuilder.getNamespace());
// Logging stats
- if (logger != null) {
+ if (logger != null && pStatsBuilder != null) {
pStatsBuilder
.getGeneralStatsBuilder()
.setStatusCode(
@@ -562,7 +629,7 @@ public final class AppSearchImpl implements Closeable {
} finally {
mReadWriteLock.writeLock().unlock();
- if (logger != null) {
+ if (logger != null && pStatsBuilder != null) {
long totalEndTimeMillis = SystemClock.elapsedRealtime();
pStatsBuilder
.getGeneralStatsBuilder()
@@ -644,6 +711,7 @@ public final class AppSearchImpl implements Closeable {
* @param databaseName The databaseName this query for.
* @param queryExpression Query String to search.
* @param searchSpec Spec for setting filters, raw query etc.
+ * @param logger logger to collect query stats
* @return The results of performing this search. It may contain an empty list of results if no
* documents matched the query.
* @throws AppSearchException on IcingSearchEngine error.
@@ -653,8 +721,17 @@ public final class AppSearchImpl implements Closeable {
@NonNull String packageName,
@NonNull String databaseName,
@NonNull String queryExpression,
- @NonNull SearchSpec searchSpec)
+ @NonNull SearchSpec searchSpec,
+ @Nullable AppSearchLogger logger)
throws AppSearchException {
+ long totalLatencyStartMillis = SystemClock.elapsedRealtime();
+ SearchStats.Builder sStatsBuilder = null;
+ if (logger != null) {
+ sStatsBuilder =
+ new SearchStats.Builder(SearchStats.VISIBILITY_SCOPE_LOCAL, packageName)
+ .setDatabase(databaseName);
+ }
+
mReadWriteLock.readLock().lock();
try {
throwIfClosedLocked();
@@ -673,9 +750,15 @@ public final class AppSearchImpl implements Closeable {
Collections.singleton(createPrefix(packageName, databaseName)),
allowedPrefixedSchemas,
queryExpression,
- searchSpec);
+ searchSpec,
+ sStatsBuilder);
} finally {
mReadWriteLock.readLock().unlock();
+ if (logger != null && sStatsBuilder != null) {
+ sStatsBuilder.setTotalLatencyMillis(
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis));
+ logger.logStats(sStatsBuilder.build());
+ }
}
}
@@ -689,6 +772,7 @@ public final class AppSearchImpl implements Closeable {
* @param searchSpec Spec for setting filters, raw query etc.
* @param callerPackageName Package name of the caller, should belong to the {@code callerUid}.
* @param callerUid UID of the client making the globalQuery call.
+ * @param logger logger to collect globalQuery stats
* @return The results of performing this search. It may contain an empty list of results if no
* documents matched the query.
* @throws AppSearchException on IcingSearchEngine error.
@@ -698,8 +782,16 @@ public final class AppSearchImpl implements Closeable {
@NonNull String queryExpression,
@NonNull SearchSpec searchSpec,
@NonNull String callerPackageName,
- int callerUid)
+ int callerUid,
+ @Nullable AppSearchLogger logger)
throws AppSearchException {
+ long totalLatencyStartMillis = SystemClock.elapsedRealtime();
+ SearchStats.Builder sStatsBuilder = null;
+ if (logger != null) {
+ sStatsBuilder =
+ new SearchStats.Builder(SearchStats.VISIBILITY_SCOPE_GLOBAL, callerPackageName);
+ }
+
mReadWriteLock.readLock().lock();
try {
throwIfClosedLocked();
@@ -754,9 +846,19 @@ public final class AppSearchImpl implements Closeable {
}
return doQueryLocked(
- prefixFilters, allowedPrefixedSchemas, queryExpression, searchSpec);
+ prefixFilters,
+ allowedPrefixedSchemas,
+ queryExpression,
+ searchSpec,
+ sStatsBuilder);
} finally {
mReadWriteLock.readLock().unlock();
+
+ if (logger != null && sStatsBuilder != null) {
+ sStatsBuilder.setTotalLatencyMillis(
+ (int) (SystemClock.elapsedRealtime() - totalLatencyStartMillis));
+ logger.logStats(sStatsBuilder.build());
+ }
}
}
@@ -794,8 +896,11 @@ public final class AppSearchImpl implements Closeable {
@NonNull Set<String> prefixes,
@NonNull Set<String> allowedPrefixedSchemas,
@NonNull String queryExpression,
- @NonNull SearchSpec searchSpec)
+ @NonNull SearchSpec searchSpec,
+ @Nullable SearchStats.Builder sStatsBuilder)
throws AppSearchException {
+ long rewriteSearchSpecLatencyStartMillis = SystemClock.elapsedRealtime();
+
SearchSpecProto.Builder searchSpecBuilder =
SearchSpecToProtoConverter.toSearchSpecProto(searchSpec).toBuilder()
.setQuery(queryExpression);
@@ -804,9 +909,17 @@ public final class AppSearchImpl implements Closeable {
// sending request to Icing.
if (!rewriteSearchSpecForPrefixesLocked(
searchSpecBuilder, prefixes, allowedPrefixedSchemas)) {
+ if (sStatsBuilder != null) {
+ sStatsBuilder.setRewriteSearchSpecLatencyMillis(
+ (int)
+ (SystemClock.elapsedRealtime()
+ - rewriteSearchSpecLatencyStartMillis));
+ }
return new SearchResultPage(Bundle.EMPTY);
}
+ // rewriteSearchSpec, rewriteResultSpec and convertScoringSpec are all counted in
+ // rewriteSearchSpecLatencyMillis
ResultSpecProto.Builder resultSpecBuilder =
SearchSpecToProtoConverter.toResultSpecProto(searchSpec).toBuilder();
@@ -822,15 +935,38 @@ public final class AppSearchImpl implements Closeable {
addPerNamespaceResultGroupingsLocked(
resultSpecBuilder, prefixes, searchSpec.getResultGroupingLimit());
}
- rewriteResultSpecForPrefixesLocked(resultSpecBuilder, prefixes, allowedPrefixedSchemas);
+ rewriteResultSpecForPrefixesLocked(resultSpecBuilder, prefixes, allowedPrefixedSchemas);
ScoringSpecProto scoringSpec = SearchSpecToProtoConverter.toScoringSpecProto(searchSpec);
+
+ long rewriteSearchSpecLatencyEndMillis = SystemClock.elapsedRealtime();
+
SearchResultProto searchResultProto =
mIcingSearchEngineLocked.search(
searchSpecBuilder.build(), scoringSpec, resultSpecBuilder.build());
+
+ if (sStatsBuilder != null) {
+ sStatsBuilder
+ .setStatusCode(
+ statusProtoToAppSearchException(searchResultProto.getStatus())
+ .getResultCode())
+ .setRewriteSearchSpecLatencyMillis(
+ (int)
+ (rewriteSearchSpecLatencyEndMillis
+ - rewriteSearchSpecLatencyStartMillis));
+ AppSearchLoggerHelper.copyNativeStats(searchResultProto.getQueryStats(), sStatsBuilder);
+ }
+
checkSuccess(searchResultProto.getStatus());
- return rewriteSearchResultProto(searchResultProto, mSchemaMapLocked);
+ long rewriteSearchResultLatencyStartMillis = SystemClock.elapsedRealtime();
+ SearchResultPage resultPage = rewriteSearchResultProto(searchResultProto, mSchemaMapLocked);
+ if (sStatsBuilder != null) {
+ sStatsBuilder.setRewriteSearchResultLatencyMillis(
+ (int) (SystemClock.elapsedRealtime() - rewriteSearchResultLatencyStartMillis));
+ }
+
+ return resultPage;
}
/**
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 0f23d926648b..97c886922c32 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
@@ -20,7 +20,9 @@ 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.PutDocumentStats;
+import com.android.server.appsearch.external.localstorage.stats.SearchStats;
/**
* An interface for implementing client-defined logging AppSearch operations stats.
@@ -39,5 +41,11 @@ public interface AppSearchLogger {
/** Logs {@link PutDocumentStats} */
void logStats(@NonNull PutDocumentStats stats) throws AppSearchException;
+ /** Logs {@link InitializeStats} */
+ void logStats(@NonNull InitializeStats stats) throws AppSearchException;
+
+ /** Logs {@link SearchStats} */
+ void logStats(@NonNull SearchStats stats) throws AppSearchException;
+
// 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 cdd795207e0b..4a5ecf1bc0b9 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
@@ -18,9 +18,13 @@ 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.PutDocumentStats;
+import com.android.server.appsearch.external.localstorage.stats.SearchStats;
+import com.google.android.icing.proto.InitializeStatsProto;
import com.google.android.icing.proto.PutDocumentStatsProto;
+import com.google.android.icing.proto.QueryStatsProto;
import java.util.Objects;
@@ -35,7 +39,7 @@ public final class AppSearchLoggerHelper {
private AppSearchLoggerHelper() {}
/**
- * Copies native stats to builder.
+ * Copies native PutDocument stats to builder.
*
* @param fromNativeStats stats copied from
* @param toStatsBuilder stats copied to
@@ -56,4 +60,64 @@ public final class AppSearchLoggerHelper {
.setNativeExceededMaxNumTokens(
fromNativeStats.getTokenizationStats().getExceededMaxTokenNum());
}
+
+ /**
+ * Copies native Initialize stats to builder.
+ *
+ * @param fromNativeStats stats copied from
+ * @param toStatsBuilder stats copied to
+ */
+ static void copyNativeStats(
+ @NonNull InitializeStatsProto fromNativeStats,
+ @NonNull InitializeStats.Builder toStatsBuilder) {
+ Objects.requireNonNull(fromNativeStats);
+ Objects.requireNonNull(toStatsBuilder);
+ toStatsBuilder
+ .setNativeLatencyMillis(fromNativeStats.getLatencyMs())
+ .setDocumentStoreRecoveryCause(
+ fromNativeStats.getDocumentStoreRecoveryCause().getNumber())
+ .setIndexRestorationCause(fromNativeStats.getIndexRestorationCause().getNumber())
+ .setSchemaStoreRecoveryCause(
+ fromNativeStats.getSchemaStoreRecoveryCause().getNumber())
+ .setDocumentStoreRecoveryLatencyMillis(
+ fromNativeStats.getDocumentStoreRecoveryLatencyMs())
+ .setIndexRestorationLatencyMillis(fromNativeStats.getIndexRestorationLatencyMs())
+ .setSchemaStoreRecoveryLatencyMillis(
+ fromNativeStats.getSchemaStoreRecoveryLatencyMs())
+ .setDocumentStoreDataStatus(
+ fromNativeStats.getDocumentStoreDataStatus().getNumber())
+ .setDocumentCount(fromNativeStats.getNumDocuments())
+ .setSchemaTypeCount(fromNativeStats.getNumSchemaTypes());
+ }
+
+ /*
+ * Copy native Query stats to buiilder.
+ *
+ * @param fromNativeStats Stats copied from.
+ * @param toStatsBuilder Stats copied to.
+ */
+ static void copyNativeStats(
+ @NonNull QueryStatsProto fromNativeStats, @NonNull SearchStats.Builder toStatsBuilder) {
+ Objects.requireNonNull(fromNativeStats);
+ Objects.requireNonNull(toStatsBuilder);
+ toStatsBuilder
+ .setNativeLatencyMillis(fromNativeStats.getLatencyMs())
+ .setTermCount(fromNativeStats.getNumTerms())
+ // TODO(b/173532925) query length missing in native
+ // .setNativeQueryLength(0)
+ .setFilteredNamespaceCount(fromNativeStats.getNumNamespacesFiltered())
+ .setFilteredSchemaTypeCount(fromNativeStats.getNumSchemaTypesFiltered())
+ .setRequestedPageSize(fromNativeStats.getRequestedPageSize())
+ .setCurrentPageReturnedResultCount(
+ fromNativeStats.getNumResultsReturnedCurrentPage())
+ .setIsFirstPage(fromNativeStats.getIsFirstPage())
+ .setParseQueryLatencyMillis(fromNativeStats.getParseQueryLatencyMs())
+ .setRankingStrategy(fromNativeStats.getRankingStrategy().getNumber())
+ .setScoredDocumentCount(fromNativeStats.getNumDocumentsScored())
+ .setScoringLatencyMillis(fromNativeStats.getScoringLatencyMs())
+ .setRankingLatencyMillis(fromNativeStats.getRankingLatencyMs())
+ .setResultWithSnippetsCount(fromNativeStats.getNumResultsWithSnippets())
+ .setDocumentRetrievingLatencyMillis(
+ fromNativeStats.getDocumentRetrievalLatencyMs());
+ }
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/InitializeStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/InitializeStats.java
new file mode 100644
index 000000000000..5364a0caa1aa
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/InitializeStats.java
@@ -0,0 +1,404 @@
+/*
+ * 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.IntDef;
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchResult;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Class holds detailed stats for initialization
+ *
+ * @hide
+ */
+public final class InitializeStats {
+ /**
+ * The cause of IcingSearchEngine recovering from a previous bad state during initialization.
+ */
+ @IntDef(
+ value = {
+ // It needs to be sync with RecoveryCause in
+ // external/icing/proto/icing/proto/logging.proto#InitializeStatsProto
+ RECOVERY_CAUSE_NONE,
+ RECOVERY_CAUSE_DATA_LOSS,
+ RECOVERY_CAUSE_INCONSISTENT_WITH_GROUND_TRUTH,
+ RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH,
+ RECOVERY_CAUSE_IO_ERROR,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RecoveryCause {}
+
+ // No recovery happened.
+ public static final int RECOVERY_CAUSE_NONE = 0;
+ // Data loss in ground truth.
+ public static final int RECOVERY_CAUSE_DATA_LOSS = 1;
+ // Data in index is inconsistent with ground truth.
+ public static final int RECOVERY_CAUSE_INCONSISTENT_WITH_GROUND_TRUTH = 2;
+ // Total checksum of all the components does not match.
+ public static final int RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH = 3;
+ // Random I/O errors.
+ public static final int RECOVERY_CAUSE_IO_ERROR = 4;
+
+ /** Status regarding how much data is lost during the initialization. */
+ @IntDef(
+ value = {
+ // It needs to be sync with DocumentStoreDataStatus in
+ // external/icing/proto/icing/proto/logging.proto#InitializeStatsProto
+
+ DOCUMENT_STORE_DATA_STATUS_NO_DATA_LOSS,
+ DOCUMENT_STORE_DATA_STATUS_PARTIAL_LOSS,
+ DOCUMENT_STORE_DATA_STATUS_COMPLETE_LOSS,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DocumentStoreDataStatus {}
+
+ // Document store is successfully initialized or fully recovered.
+ public static final int DOCUMENT_STORE_DATA_STATUS_NO_DATA_LOSS = 0;
+ // Ground truth data is partially lost.
+ public static final int DOCUMENT_STORE_DATA_STATUS_PARTIAL_LOSS = 1;
+ // Ground truth data is completely lost.
+ public static final int DOCUMENT_STORE_DATA_STATUS_COMPLETE_LOSS = 2;
+
+ @AppSearchResult.ResultCode private final int mStatusCode;
+ private final int mTotalLatencyMillis;
+ /** Whether the initialize() detects deSync. */
+ private final boolean mHasDeSync;
+ /** Time used to read and process the schema and namespaces. */
+ private final int mPrepareSchemaAndNamespacesLatencyMillis;
+ /** Time used to read and process the visibility store. */
+ private final int mPrepareVisibilityStoreLatencyMillis;
+ /** Overall time used for the native function call. */
+ private final int mNativeLatencyMillis;
+
+ @RecoveryCause private final int mNativeDocumentStoreRecoveryCause;
+ @RecoveryCause private final int mNativeIndexRestorationCause;
+ @RecoveryCause private final int mNativeSchemaStoreRecoveryCause;
+ /** Time used to recover the document store. */
+ private final int mNativeDocumentStoreRecoveryLatencyMillis;
+ /** Time used to restore the index. */
+ private final int mNativeIndexRestorationLatencyMillis;
+ /** Time used to recover the schema store. */
+ private final int mNativeSchemaStoreRecoveryLatencyMillis;
+ /** Status regarding how much data is lost during the initialization. */
+ private final int mNativeDocumentStoreDataStatus;
+ /**
+ * Returns number of documents currently in document store. Those may include alive, deleted,
+ * and expired documents.
+ */
+ private final int mNativeNumDocuments;
+ /** Returns number of schema types currently in the schema store. */
+ private final int mNativeNumSchemaTypes;
+
+ /** Returns the status of the initialization. */
+ @AppSearchResult.ResultCode
+ public int getStatusCode() {
+ return mStatusCode;
+ }
+
+ /** Returns the total latency in milliseconds for the initialization. */
+ public int getTotalLatencyMillis() {
+ return mTotalLatencyMillis;
+ }
+
+ /**
+ * Returns whether the initialize() detects deSync.
+ *
+ * <p>If there is a deSync, it means AppSearch and IcingSearchEngine have an inconsistent view
+ * of what data should exist.
+ */
+ public boolean hasDeSync() {
+ return mHasDeSync;
+ }
+
+ /** Returns time used to read and process the schema and namespaces. */
+ public int getPrepareSchemaAndNamespacesLatencyMillis() {
+ return mPrepareSchemaAndNamespacesLatencyMillis;
+ }
+
+ /** Returns time used to read and process the visibility file. */
+ public int getPrepareVisibilityStoreLatencyMillis() {
+ return mPrepareVisibilityStoreLatencyMillis;
+ }
+
+ /** Returns overall time used for the native function call. */
+ public int getNativeLatencyMillis() {
+ return mNativeLatencyMillis;
+ }
+
+ /**
+ * Returns recovery cause for document store.
+ *
+ * <p>Possible recovery causes for document store:
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_DATA_LOSS}
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH}
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_IO_ERROR}
+ */
+ @RecoveryCause
+ public int getDocumentStoreRecoveryCause() {
+ return mNativeDocumentStoreRecoveryCause;
+ }
+
+ /**
+ * Returns restoration cause for index store.
+ *
+ * <p>Possible causes:
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_INCONSISTENT_WITH_GROUND_TRUTH}
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH}
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_IO_ERROR}
+ */
+ @RecoveryCause
+ public int getIndexRestorationCause() {
+ return mNativeIndexRestorationCause;
+ }
+
+ /**
+ * Returns recovery cause for schema store.
+ *
+ * <p>Possible causes:
+ * <li>IO_ERROR
+ */
+ @RecoveryCause
+ public int getSchemaStoreRecoveryCause() {
+ return mNativeSchemaStoreRecoveryCause;
+ }
+
+ /** Returns time used to recover the document store. */
+ public int getDocumentStoreRecoveryLatencyMillis() {
+ return mNativeDocumentStoreRecoveryLatencyMillis;
+ }
+
+ /** Returns time used to restore the index. */
+ public int getIndexRestorationLatencyMillis() {
+ return mNativeIndexRestorationLatencyMillis;
+ }
+
+ /** Returns time used to recover the schema store. */
+ public int getSchemaStoreRecoveryLatencyMillis() {
+ return mNativeSchemaStoreRecoveryLatencyMillis;
+ }
+
+ /** Returns status about how much data is lost during the initialization. */
+ @DocumentStoreDataStatus
+ public int getDocumentStoreDataStatus() {
+ return mNativeDocumentStoreDataStatus;
+ }
+
+ /**
+ * Returns number of documents currently in document store. Those may include alive, deleted,
+ * and expired documents.
+ */
+ public int getDocumentCount() {
+ return mNativeNumDocuments;
+ }
+
+ /** Returns number of schema types currently in the schema store. */
+ public int getSchemaTypeCount() {
+ return mNativeNumSchemaTypes;
+ }
+
+ InitializeStats(@NonNull Builder builder) {
+ Objects.requireNonNull(builder);
+ mStatusCode = builder.mStatusCode;
+ mTotalLatencyMillis = builder.mTotalLatencyMillis;
+ mHasDeSync = builder.mHasDeSync;
+ mPrepareSchemaAndNamespacesLatencyMillis = builder.mPrepareSchemaAndNamespacesLatencyMillis;
+ mPrepareVisibilityStoreLatencyMillis = builder.mPrepareVisibilityStoreLatencyMillis;
+ mNativeLatencyMillis = builder.mNativeLatencyMillis;
+ mNativeDocumentStoreRecoveryCause = builder.mNativeDocumentStoreRecoveryCause;
+ mNativeIndexRestorationCause = builder.mNativeIndexRestorationCause;
+ mNativeSchemaStoreRecoveryCause = builder.mNativeSchemaStoreRecoveryCause;
+ mNativeDocumentStoreRecoveryLatencyMillis =
+ builder.mNativeDocumentStoreRecoveryLatencyMillis;
+ mNativeIndexRestorationLatencyMillis = builder.mNativeIndexRestorationLatencyMillis;
+ mNativeSchemaStoreRecoveryLatencyMillis = builder.mNativeSchemaStoreRecoveryLatencyMillis;
+ mNativeDocumentStoreDataStatus = builder.mNativeDocumentStoreDataStatus;
+ mNativeNumDocuments = builder.mNativeNumDocuments;
+ mNativeNumSchemaTypes = builder.mNativeNumSchemaTypes;
+ }
+
+ /** Builder for {@link InitializeStats}. */
+ public static class Builder {
+ @AppSearchResult.ResultCode int mStatusCode;
+ int mTotalLatencyMillis;
+ boolean mHasDeSync;
+ int mPrepareSchemaAndNamespacesLatencyMillis;
+ int mPrepareVisibilityStoreLatencyMillis;
+ int mNativeLatencyMillis;
+ @RecoveryCause int mNativeDocumentStoreRecoveryCause;
+ @RecoveryCause int mNativeIndexRestorationCause;
+ @RecoveryCause int mNativeSchemaStoreRecoveryCause;
+ int mNativeDocumentStoreRecoveryLatencyMillis;
+ int mNativeIndexRestorationLatencyMillis;
+ int mNativeSchemaStoreRecoveryLatencyMillis;
+ @DocumentStoreDataStatus int mNativeDocumentStoreDataStatus;
+ int mNativeNumDocuments;
+ int mNativeNumSchemaTypes;
+
+ /** Sets the status of the initialization. */
+ @NonNull
+ public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) {
+ mStatusCode = statusCode;
+ return this;
+ }
+
+ /** Sets the total latency of the initialization in milliseconds. */
+ @NonNull
+ public Builder setTotalLatencyMillis(int totalLatencyMillis) {
+ mTotalLatencyMillis = totalLatencyMillis;
+ return this;
+ }
+
+ /**
+ * Sets whether the initialize() detects deSync.
+ *
+ * <p>If there is a deSync, it means AppSearch and IcingSearchEngine have an inconsistent
+ * view of what data should exist.
+ */
+ @NonNull
+ public Builder setHasDeSync(boolean hasDeSync) {
+ mHasDeSync = hasDeSync;
+ return this;
+ }
+
+ /** Sets time used to read and process the schema and namespaces. */
+ @NonNull
+ public Builder setPrepareSchemaAndNamespacesLatencyMillis(
+ int prepareSchemaAndNamespacesLatencyMillis) {
+ mPrepareSchemaAndNamespacesLatencyMillis = prepareSchemaAndNamespacesLatencyMillis;
+ return this;
+ }
+
+ /** Sets time used to read and process the visibility file. */
+ @NonNull
+ public Builder setPrepareVisibilityStoreLatencyMillis(
+ int prepareVisibilityStoreLatencyMillis) {
+ mPrepareVisibilityStoreLatencyMillis = prepareVisibilityStoreLatencyMillis;
+ return this;
+ }
+
+ /** Sets overall time used for the native function call. */
+ @NonNull
+ public Builder setNativeLatencyMillis(int nativeLatencyMillis) {
+ mNativeLatencyMillis = nativeLatencyMillis;
+ return this;
+ }
+
+ /**
+ * Sets recovery cause for document store.
+ *
+ * <p>Possible recovery causes for document store:
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_DATA_LOSS}
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH}
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_IO_ERROR}
+ */
+ @NonNull
+ public Builder setDocumentStoreRecoveryCause(
+ @RecoveryCause int documentStoreRecoveryCause) {
+ mNativeDocumentStoreRecoveryCause = documentStoreRecoveryCause;
+ return this;
+ }
+
+ /**
+ * Sets restoration cause for index store.
+ *
+ * <p>Possible causes:
+ * <li>{@link InitializeStats#DOCUMENT_STORE_DATA_STATUS_COMPLETE_LOSS}
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_TOTAL_CHECKSUM_MISMATCH}
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_IO_ERROR}
+ */
+ @NonNull
+ public Builder setIndexRestorationCause(@RecoveryCause int indexRestorationCause) {
+ mNativeIndexRestorationCause = indexRestorationCause;
+ return this;
+ }
+
+ /**
+ * Returns recovery cause for schema store.
+ *
+ * <p>Possible causes:
+ * <li>{@link InitializeStats#RECOVERY_CAUSE_IO_ERROR}
+ */
+ @NonNull
+ public Builder setSchemaStoreRecoveryCause(@RecoveryCause int schemaStoreRecoveryCause) {
+ mNativeSchemaStoreRecoveryCause = schemaStoreRecoveryCause;
+ return this;
+ }
+
+ /** Sets time used to recover the document store. */
+ @NonNull
+ public Builder setDocumentStoreRecoveryLatencyMillis(
+ int documentStoreRecoveryLatencyMillis) {
+ mNativeDocumentStoreRecoveryLatencyMillis = documentStoreRecoveryLatencyMillis;
+ return this;
+ }
+
+ /** Sets time used to restore the index. */
+ @NonNull
+ public Builder setIndexRestorationLatencyMillis(int indexRestorationLatencyMillis) {
+ mNativeIndexRestorationLatencyMillis = indexRestorationLatencyMillis;
+ return this;
+ }
+
+ /** Sets time used to recover the schema store. */
+ @NonNull
+ public Builder setSchemaStoreRecoveryLatencyMillis(int schemaStoreRecoveryLatencyMillis) {
+ mNativeSchemaStoreRecoveryLatencyMillis = schemaStoreRecoveryLatencyMillis;
+ return this;
+ }
+
+ /**
+ * Sets Native Document Store Data status. status is defined in
+ * external/icing/proto/icing/proto/logging.proto
+ */
+ @NonNull
+ public Builder setDocumentStoreDataStatus(
+ @DocumentStoreDataStatus int documentStoreDataStatus) {
+ mNativeDocumentStoreDataStatus = documentStoreDataStatus;
+ return this;
+ }
+
+ /**
+ * Sets number of documents currently in document store. Those may include alive, deleted,
+ * and expired documents.
+ */
+ @NonNull
+ public Builder setDocumentCount(int numDocuments) {
+ mNativeNumDocuments = numDocuments;
+ return this;
+ }
+
+ /** Sets number of schema types currently in the schema store. */
+ @NonNull
+ public Builder setSchemaTypeCount(int numSchemaTypes) {
+ mNativeNumSchemaTypes = numSchemaTypes;
+ return this;
+ }
+
+ /**
+ * Constructs a new {@link InitializeStats} from the contents of this {@link
+ * InitializeStats.Builder}
+ */
+ @NonNull
+ public InitializeStats build() {
+ return new InitializeStats(/* builder= */ this);
+ }
+ }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SearchStats.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SearchStats.java
new file mode 100644
index 000000000000..7b22b2f23142
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/stats/SearchStats.java
@@ -0,0 +1,460 @@
+/*
+ * 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.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.SearchSpec;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Class holds detailed stats for {@link android.app.appsearch.AppSearchSession#search(String,
+ * SearchSpec)}
+ *
+ * @hide
+ */
+public final class SearchStats {
+ @IntDef(
+ value = {
+ // Searches apps' own documents.
+ VISIBILITY_SCOPE_LOCAL,
+ // Searches the global documents. Including platform surfaceable and 3p-access.
+ VISIBILITY_SCOPE_GLOBAL,
+ // TODO(b/173532925) Add THIRD_PARTY_ACCESS once we can distinguish platform
+ // surfaceable from 3p access(right both of them are categorized as
+ // VISIBILITY_SCOPE_GLOBAL)
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VisibilityScope {}
+
+ // Searches apps' own documents.
+ public static final int VISIBILITY_SCOPE_LOCAL = 1;
+ // Searches the global documents. Including platform surfaceable and 3p-access.
+ public static final int VISIBILITY_SCOPE_GLOBAL = 2;
+
+ @NonNull private final String mPackageName;
+ @Nullable private final String mDatabase;
+ /**
+ * The status code returned by {@link AppSearchResult#getResultCode()} for the call or internal
+ * state.
+ */
+ @AppSearchResult.ResultCode private final int mStatusCode;
+
+ private final int mTotalLatencyMillis;
+ /** Time used to rewrite the search spec. */
+ private final int mRewriteSearchSpecLatencyMillis;
+ /** Time used to rewrite the search results. */
+ private final int mRewriteSearchResultLatencyMillis;
+ /** Defines the scope the query is searching over */
+ @VisibilityScope private final int mVisibilityScope;
+ /** Overall time used for the native function call. */
+ private final int mNativeLatencyMillis;
+ /** Number of terms in the query string. */
+ private final int mNativeNumTerms;
+ /** Length of the query string. */
+ private final int mNativeQueryLength;
+ /** Number of namespaces filtered. */
+ private final int mNativeNumNamespacesFiltered;
+ /** Number of schema types filtered. */
+ private final int mNativeNumSchemaTypesFiltered;
+ /** The requested number of results in one page. */
+ private final int mNativeRequestedPageSize;
+ /** The actual number of results returned in the current page. */
+ private final int mNativeNumResultsReturnedCurrentPage;
+ /**
+ * Whether the function call is querying the first page. If it's not, Icing will fetch the
+ * results from cache so that some steps may be skipped.
+ */
+ private final boolean mNativeIsFirstPage;
+ /**
+ * Time used to parse the query, including 2 parts: tokenizing and transforming tokens into an
+ * iterator tree.
+ */
+ private final int mNativeParseQueryLatencyMillis;
+ /** Strategy of scoring and ranking. */
+ @SearchSpec.RankingStrategy private final int mNativeRankingStrategy;
+ /** Number of documents scored. */
+ private final int mNativeNumDocumentsScored;
+ /** Time used to score the raw results. */
+ private final int mNativeScoringLatencyMillis;
+ /** Time used to rank the scored results. */
+ private final int mNativeRankingLatencyMillis;
+ /**
+ * Time used to fetch the document protos. Note that it includes the time to snippet if {@link
+ * SearchStats#mNativeNumResultsWithSnippets} is greater than 0.
+ */
+ private final int mNativeDocumentRetrievingLatencyMillis;
+ /** How many snippets are calculated. */
+ private final int mNativeNumResultsWithSnippets;
+
+ SearchStats(@NonNull Builder builder) {
+ Objects.requireNonNull(builder);
+ mPackageName = builder.mPackageName;
+ mDatabase = builder.mDatabase;
+ mStatusCode = builder.mStatusCode;
+ mTotalLatencyMillis = builder.mTotalLatencyMillis;
+ mRewriteSearchSpecLatencyMillis = builder.mRewriteSearchSpecLatencyMillis;
+ mRewriteSearchResultLatencyMillis = builder.mRewriteSearchResultLatencyMillis;
+ mVisibilityScope = builder.mVisibilityScope;
+ mNativeLatencyMillis = builder.mNativeLatencyMillis;
+ mNativeNumTerms = builder.mNativeNumTerms;
+ mNativeQueryLength = builder.mNativeQueryLength;
+ mNativeNumNamespacesFiltered = builder.mNativeNumNamespacesFiltered;
+ mNativeNumSchemaTypesFiltered = builder.mNativeNumSchemaTypesFiltered;
+ mNativeRequestedPageSize = builder.mNativeRequestedPageSize;
+ mNativeNumResultsReturnedCurrentPage = builder.mNativeNumResultsReturnedCurrentPage;
+ mNativeIsFirstPage = builder.mNativeIsFirstPage;
+ mNativeParseQueryLatencyMillis = builder.mNativeParseQueryLatencyMillis;
+ mNativeRankingStrategy = builder.mNativeRankingStrategy;
+ mNativeNumDocumentsScored = builder.mNativeNumDocumentsScored;
+ mNativeScoringLatencyMillis = builder.mNativeScoringLatencyMillis;
+ mNativeRankingLatencyMillis = builder.mNativeRankingLatencyMillis;
+ mNativeNumResultsWithSnippets = builder.mNativeNumResultsWithSnippets;
+ mNativeDocumentRetrievingLatencyMillis = builder.mNativeDocumentRetrievingLatencyMillis;
+ }
+
+ /** Returns the package name of the session. */
+ @NonNull
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * Returns the database name of the session.
+ *
+ * @return database name used by the session. {@code null} if and only if it is a global
+ * search(visibilityScope is {@link SearchStats#VISIBILITY_SCOPE_GLOBAL}).
+ */
+ @Nullable
+ public String getDatabase() {
+ return mDatabase;
+ }
+
+ /** Returns status of the search. */
+ @AppSearchResult.ResultCode
+ public int getStatusCode() {
+ return mStatusCode;
+ }
+
+ /** Returns the total latency of the search. */
+ public int getTotalLatencyMillis() {
+ return mTotalLatencyMillis;
+ }
+
+ /** Returns how much time spent on rewriting the {@link SearchSpec}. */
+ public int getRewriteSearchSpecLatencyMillis() {
+ return mRewriteSearchSpecLatencyMillis;
+ }
+
+ /** Returns how much time spent on rewriting the {@link android.app.appsearch.SearchResult}. */
+ public int getRewriteSearchResultLatencyMillis() {
+ return mRewriteSearchResultLatencyMillis;
+ }
+
+ /** Returns the visibility scope of the search. */
+ @VisibilityScope
+ public int getVisibilityScope() {
+ return mVisibilityScope;
+ }
+
+ /** Returns how much time spent on the native calls. */
+ public int getNativeLatencyMillis() {
+ return mNativeLatencyMillis;
+ }
+
+ /** Returns number of terms in the search string. */
+ public int getTermCount() {
+ return mNativeNumTerms;
+ }
+
+ /** Returns the length of the search string. */
+ public int getQueryLength() {
+ return mNativeQueryLength;
+ }
+
+ /** Returns number of namespaces filtered. */
+ public int getFilteredNamespaceCount() {
+ return mNativeNumNamespacesFiltered;
+ }
+
+ /** Returns number of schema types filtered. */
+ public int getFilteredSchemaTypeCount() {
+ return mNativeNumSchemaTypesFiltered;
+ }
+
+ /** Returns the requested number of results in one page. */
+ public int getRequestedPageSize() {
+ return mNativeRequestedPageSize;
+ }
+
+ /** Returns the actual number of results returned in the current page. */
+ public int getCurrentPageReturnedResultCount() {
+ return mNativeNumResultsReturnedCurrentPage;
+ }
+
+ // TODO(b/185184738) Make it an integer to show how many pages having been returned.
+ /** Returns whether the function call is querying the first page. */
+ public boolean isFirstPage() {
+ return mNativeIsFirstPage;
+ }
+
+ /**
+ * Returns time used to parse the query, including 2 parts: tokenizing and transforming tokens
+ * into an iterator tree.
+ */
+ public int getParseQueryLatencyMillis() {
+ return mNativeParseQueryLatencyMillis;
+ }
+
+ /** Returns strategy of scoring and ranking. */
+ @SearchSpec.RankingStrategy
+ public int getRankingStrategy() {
+ return mNativeRankingStrategy;
+ }
+
+ /** Returns number of documents scored. */
+ public int getScoredDocumentCount() {
+ return mNativeNumDocumentsScored;
+ }
+
+ /** Returns time used to score the raw results. */
+ public int getScoringLatencyMillis() {
+ return mNativeScoringLatencyMillis;
+ }
+
+ /** Returns time used to rank the scored results. */
+ public int getRankingLatencyMillis() {
+ return mNativeRankingLatencyMillis;
+ }
+
+ /**
+ * Returns time used to fetch the document protos. Note that it includes the time to snippet if
+ * {@link SearchStats#mNativeNumResultsWithSnippets} is not zero.
+ */
+ public int getDocumentRetrievingLatencyMillis() {
+ return mNativeDocumentRetrievingLatencyMillis;
+ }
+
+ /** Returns the number of the results in the page returned were snippeted. */
+ public int getResultWithSnippetsCount() {
+ return mNativeNumResultsWithSnippets;
+ }
+
+ /** Builder for {@link SearchStats} */
+ public static class Builder {
+ @NonNull final String mPackageName;
+ @Nullable String mDatabase;
+ @AppSearchResult.ResultCode int mStatusCode;
+ int mTotalLatencyMillis;
+ int mRewriteSearchSpecLatencyMillis;
+ int mRewriteSearchResultLatencyMillis;
+ int mVisibilityScope;
+ int mNativeLatencyMillis;
+ int mNativeNumTerms;
+ int mNativeQueryLength;
+ int mNativeNumNamespacesFiltered;
+ int mNativeNumSchemaTypesFiltered;
+ int mNativeRequestedPageSize;
+ int mNativeNumResultsReturnedCurrentPage;
+ boolean mNativeIsFirstPage;
+ int mNativeParseQueryLatencyMillis;
+ int mNativeRankingStrategy;
+ int mNativeNumDocumentsScored;
+ int mNativeScoringLatencyMillis;
+ int mNativeRankingLatencyMillis;
+ int mNativeNumResultsWithSnippets;
+ int mNativeDocumentRetrievingLatencyMillis;
+
+ /**
+ * Constructor
+ *
+ * @param visibilityScope scope for the corresponding search.
+ * @param packageName name of the calling package.
+ */
+ public Builder(@VisibilityScope int visibilityScope, @NonNull String packageName) {
+ mVisibilityScope = visibilityScope;
+ mPackageName = Objects.requireNonNull(packageName);
+ }
+
+ /** Sets the database used by the session. */
+ @NonNull
+ public Builder setDatabase(@NonNull String database) {
+ mDatabase = Objects.requireNonNull(database);
+ return this;
+ }
+
+ /** Sets the status of the search. */
+ @NonNull
+ public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) {
+ mStatusCode = statusCode;
+ return this;
+ }
+
+ /** Sets total latency for the search. */
+ @NonNull
+ public Builder setTotalLatencyMillis(int totalLatencyMillis) {
+ mTotalLatencyMillis = totalLatencyMillis;
+ return this;
+ }
+
+ /** Sets time used to rewrite the search spec. */
+ @NonNull
+ public Builder setRewriteSearchSpecLatencyMillis(int rewriteSearchSpecLatencyMillis) {
+ mRewriteSearchSpecLatencyMillis = rewriteSearchSpecLatencyMillis;
+ return this;
+ }
+
+ /** Sets time used to rewrite the search results. */
+ @NonNull
+ public Builder setRewriteSearchResultLatencyMillis(int rewriteSearchResultLatencyMillis) {
+ mRewriteSearchResultLatencyMillis = rewriteSearchResultLatencyMillis;
+ return this;
+ }
+
+ /** Sets overall time used for the native function calls. */
+ @NonNull
+ public Builder setNativeLatencyMillis(int nativeLatencyMillis) {
+ mNativeLatencyMillis = nativeLatencyMillis;
+ return this;
+ }
+
+ /** Sets number of terms in the search string. */
+ @NonNull
+ public Builder setTermCount(int termCount) {
+ mNativeNumTerms = termCount;
+ return this;
+ }
+
+ /** Sets length of the search string. */
+ @NonNull
+ public Builder setQueryLength(int queryLength) {
+ mNativeQueryLength = queryLength;
+ return this;
+ }
+
+ /** Sets number of namespaces filtered. */
+ @NonNull
+ public Builder setFilteredNamespaceCount(int filteredNamespaceCount) {
+ mNativeNumNamespacesFiltered = filteredNamespaceCount;
+ return this;
+ }
+
+ /** Sets number of schema types filtered. */
+ @NonNull
+ public Builder setFilteredSchemaTypeCount(int filteredSchemaTypeCount) {
+ mNativeNumSchemaTypesFiltered = filteredSchemaTypeCount;
+ return this;
+ }
+
+ /** Sets the requested number of results in one page. */
+ @NonNull
+ public Builder setRequestedPageSize(int requestedPageSize) {
+ mNativeRequestedPageSize = requestedPageSize;
+ return this;
+ }
+
+ /** Sets the actual number of results returned in the current page. */
+ @NonNull
+ public Builder setCurrentPageReturnedResultCount(int currentPageReturnedResultCount) {
+ mNativeNumResultsReturnedCurrentPage = currentPageReturnedResultCount;
+ return this;
+ }
+
+ /**
+ * Sets whether the function call is querying the first page. If it's not, Icing will fetch
+ * the results from cache so that some steps may be skipped.
+ */
+ @NonNull
+ public Builder setIsFirstPage(boolean nativeIsFirstPage) {
+ mNativeIsFirstPage = nativeIsFirstPage;
+ return this;
+ }
+
+ /**
+ * Sets time used to parse the query, including 2 parts: tokenizing and transforming tokens
+ * into an iterator tree.
+ */
+ @NonNull
+ public Builder setParseQueryLatencyMillis(int parseQueryLatencyMillis) {
+ mNativeParseQueryLatencyMillis = parseQueryLatencyMillis;
+ return this;
+ }
+
+ /** Sets strategy of scoring and ranking. */
+ @NonNull
+ public Builder setRankingStrategy(@SearchSpec.RankingStrategy int rankingStrategy) {
+ mNativeRankingStrategy = rankingStrategy;
+ return this;
+ }
+
+ /** Sets number of documents scored. */
+ @NonNull
+ public Builder setScoredDocumentCount(int scoredDocumentCount) {
+ mNativeNumDocumentsScored = scoredDocumentCount;
+ return this;
+ }
+
+ /** Sets time used to score the raw results. */
+ @NonNull
+ public Builder setScoringLatencyMillis(int scoringLatencyMillis) {
+ mNativeScoringLatencyMillis = scoringLatencyMillis;
+ return this;
+ }
+
+ /** Sets time used to rank the scored results. */
+ @NonNull
+ public Builder setRankingLatencyMillis(int rankingLatencyMillis) {
+ mNativeRankingLatencyMillis = rankingLatencyMillis;
+ return this;
+ }
+
+ /** Sets time used to fetch the document protos. */
+ @NonNull
+ public Builder setDocumentRetrievingLatencyMillis(int documentRetrievingLatencyMillis) {
+ mNativeDocumentRetrievingLatencyMillis = documentRetrievingLatencyMillis;
+ return this;
+ }
+
+ /** Sets how many snippets are calculated. */
+ @NonNull
+ public Builder setResultWithSnippetsCount(int resultWithSnippetsCount) {
+ mNativeNumResultsWithSnippets = resultWithSnippetsCount;
+ return this;
+ }
+
+ /**
+ * Constructs a new {@link SearchStats} from the contents of this {@link
+ * SearchStats.Builder}.
+ */
+ @NonNull
+ public SearchStats build() {
+ if (mDatabase == null) {
+ Preconditions.checkState(
+ mVisibilityScope != SearchStats.VISIBILITY_SCOPE_LOCAL,
+ "database can not be null if visibilityScope is local.");
+ }
+
+ return new SearchStats(/* 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 731ab35bf367..88f238e91e45 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
@@ -31,7 +31,9 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
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.PutDocumentStats;
+import com.android.server.appsearch.external.localstorage.stats.SearchStats;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
@@ -189,6 +191,16 @@ public final class PlatformLogger implements AppSearchLogger {
}
}
+ @Override
+ public void logStats(@NonNull InitializeStats stats) throws AppSearchException {
+ // TODO(b/173532925): Implement
+ }
+
+ @Override
+ public void logStats(@NonNull SearchStats stats) throws AppSearchException {
+ // TODO(b/173532925): Implement
+ }
+
/**
* Removes cached UID for package.
*
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index ce0ebe62f65b..10bba13a8e2f 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-I06df2c636d26419e653c5d8c9e7d15449da6816e
+I19dac52031c47099f621eced9f148931f1021f25
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
index b552fd5e8718..79e5865abd82 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
@@ -70,7 +70,8 @@ public class AppSearchImplPlatformTest {
mTemporaryFolder.newFolder(),
mContext,
mContext.getUserId(),
- mContext.getPackageName());
+ mContext.getPackageName(),
+ /*logger=*/ null);
mGlobalQuerierUid =
mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
}
@@ -117,9 +118,8 @@ public class AppSearchImplPlatformTest {
// No query filters specified, global query can retrieve all documents.
SearchSpec searchSpec =
new SearchSpec.Builder().setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY).build();
- SearchResultPage searchResultPage =
- mAppSearchImpl.globalQuery(
- "", searchSpec, mContext.getPackageName(), mGlobalQuerierUid);
+ SearchResultPage searchResultPage = mAppSearchImpl.globalQuery(
+ "", searchSpec, mContext.getPackageName(), mGlobalQuerierUid, /*logger=*/ null);
assertThat(searchResultPage.getResults()).hasSize(2);
// Document2 will be first since it got indexed later and has a "better", aka more recent
@@ -174,9 +174,8 @@ public class AppSearchImplPlatformTest {
.setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
.addFilterPackageNames("package1")
.build();
- SearchResultPage searchResultPage =
- mAppSearchImpl.globalQuery(
- "", searchSpec, mContext.getPackageName(), mGlobalQuerierUid);
+ SearchResultPage searchResultPage = mAppSearchImpl.globalQuery(
+ "", searchSpec, mContext.getPackageName(), mGlobalQuerierUid, /*logger=*/ null);
assertThat(searchResultPage.getResults()).hasSize(1);
assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document1);
@@ -186,9 +185,8 @@ public class AppSearchImplPlatformTest {
.setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
.addFilterPackageNames("package2")
.build();
- searchResultPage =
- mAppSearchImpl.globalQuery(
- "", searchSpec, mContext.getPackageName(), mGlobalQuerierUid);
+ searchResultPage = mAppSearchImpl.globalQuery(
+ "", searchSpec, mContext.getPackageName(), mGlobalQuerierUid, /*logger=*/ null);
assertThat(searchResultPage.getResults()).hasSize(1);
assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document2);
}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
index 11ae76b94495..28955d6e727f 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
@@ -67,7 +67,8 @@ public class VisibilityStoreTest {
mTemporaryFolder.newFolder(),
mContext,
mContext.getUserId(),
- /*globalQuerierPackage=*/ mContext.getPackageName());
+ /*globalQuerierPackage=*/ mContext.getPackageName(),
+ /*logger=*/ null);
mGlobalQuerierUid =
mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
@@ -163,7 +164,8 @@ public class VisibilityStoreTest {
mTemporaryFolder.newFolder(),
mContext,
mContext.getUserId(),
- /*globalQuerierPackage=*/ mContext.getPackageName());
+ /*globalQuerierPackage=*/ mContext.getPackageName(),
+ /*logger=*/ null);
VisibilityStore visibilityStore = appSearchImpl.getVisibilityStoreLocked();
// Use some arbitrary callerUid. If we can't find the global querier's uid though,
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 9a7cf803763d..b36720303a55 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
@@ -82,7 +82,8 @@ public class AppSearchImplTest {
mTemporaryFolder.newFolder(),
context,
VisibilityStore.NO_OP_USER_ID,
- /*globalQuerierPackage=*/ context.getPackageName());
+ /*globalQuerierPackage=*/ context.getPackageName(),
+ /*logger=*/ null);
}
// TODO(b/175430168) add test to verify reset is working properly.
@@ -604,7 +605,7 @@ public class AppSearchImplTest {
SearchSpec searchSpec =
new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
SearchResultPage searchResultPage =
- mAppSearchImpl.query("package", "EmptyDatabase", "", searchSpec);
+ mAppSearchImpl.query("package", "EmptyDatabase", "", searchSpec, /*logger=*/ null);
assertThat(searchResultPage.getResults()).isEmpty();
}
@@ -647,7 +648,7 @@ public class AppSearchImplTest {
SearchSpec searchSpec =
new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
SearchResultPage searchResultPage =
- mAppSearchImpl.query("package2", "database2", "", searchSpec);
+ mAppSearchImpl.query("package2", "database2", "", searchSpec, /*logger=*/ null);
assertThat(searchResultPage.getResults()).isEmpty();
// Insert package2 document
@@ -655,7 +656,9 @@ public class AppSearchImplTest {
mAppSearchImpl.putDocument("package2", "database2", document, /*logger=*/ null);
// No query filters specified. package2 should only get its own documents back.
- searchResultPage = mAppSearchImpl.query("package2", "database2", "", searchSpec);
+ searchResultPage =
+ mAppSearchImpl.query("package2", "database2", "", searchSpec, /*logger=
+ */ null);
assertThat(searchResultPage.getResults()).hasSize(1);
assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document);
}
@@ -703,7 +706,7 @@ public class AppSearchImplTest {
.addFilterPackageNames("package1")
.build();
SearchResultPage searchResultPage =
- mAppSearchImpl.query("package2", "database2", "", searchSpec);
+ mAppSearchImpl.query("package2", "database2", "", searchSpec, /*logger=*/ null);
assertThat(searchResultPage.getResults()).isEmpty();
// Insert package2 document
@@ -716,7 +719,9 @@ public class AppSearchImplTest {
.setTermMatch(TermMatchType.Code.PREFIX_VALUE)
.addFilterPackageNames("package2")
.build();
- searchResultPage = mAppSearchImpl.query("package2", "database2", "", searchSpec);
+ searchResultPage =
+ mAppSearchImpl.query("package2", "database2", "", searchSpec, /*logger=
+ */ null);
assertThat(searchResultPage.getResults()).hasSize(1);
assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document);
}
@@ -727,7 +732,11 @@ public class AppSearchImplTest {
new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
SearchResultPage searchResultPage =
mAppSearchImpl.globalQuery(
- "", searchSpec, /*callerPackageName=*/ "", /*callerUid=*/ 0);
+ "",
+ searchSpec,
+ /*callerPackageName=*/ "",
+ /*callerUid=*/ 0,
+ /*logger=*/ null);
assertThat(searchResultPage.getResults()).isEmpty();
}
@@ -1033,7 +1042,12 @@ public class AppSearchImplTest {
SearchSpec searchSpec =
new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
SearchResultPage searchResultPage =
- mAppSearchImpl.query("package", "database", /*queryExpression=*/ "", searchSpec);
+ mAppSearchImpl.query(
+ "package",
+ "database",
+ /*queryExpression=*/ "",
+ searchSpec,
+ /*logger=*/ null);
assertThat(searchResultPage.getResults()).hasSize(1);
assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document);
@@ -1042,7 +1056,12 @@ public class AppSearchImplTest {
// Verify the document is cleared.
searchResultPage =
- mAppSearchImpl.query("package2", "database2", /*queryExpression=*/ "", searchSpec);
+ mAppSearchImpl.query(
+ "package2",
+ "database2",
+ /*queryExpression=*/ "",
+ searchSpec,
+ /*logger=*/ null);
assertThat(searchResultPage.getResults()).isEmpty();
// Verify the schema is cleared.
@@ -1244,7 +1263,8 @@ public class AppSearchImplTest {
new SearchSpec.Builder()
.setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
.setRankingStrategy(SearchSpec.RANKING_STRATEGY_USAGE_COUNT)
- .build())
+ .build(),
+ /*logger=*/ null)
.getResults();
assertThat(page).hasSize(2);
assertThat(page.get(0).getGenericDocument().getId()).isEqualTo("id1");
@@ -1262,7 +1282,8 @@ public class AppSearchImplTest {
.setRankingStrategy(
SearchSpec
.RANKING_STRATEGY_USAGE_LAST_USED_TIMESTAMP)
- .build())
+ .build(),
+ /*logger=*/ null)
.getResults();
assertThat(page).hasSize(2);
assertThat(page.get(0).getGenericDocument().getId()).isEqualTo("id2");
@@ -1279,7 +1300,8 @@ public class AppSearchImplTest {
.setTermMatch(SearchSpec.TERM_MATCH_EXACT_ONLY)
.setRankingStrategy(
SearchSpec.RANKING_STRATEGY_SYSTEM_USAGE_COUNT)
- .build())
+ .build(),
+ /*logger=*/ null)
.getResults();
assertThat(page).hasSize(2);
assertThat(page.get(0).getGenericDocument().getId()).isEqualTo("id2");
@@ -1297,7 +1319,8 @@ public class AppSearchImplTest {
.setRankingStrategy(
SearchSpec
.RANKING_STRATEGY_SYSTEM_USAGE_LAST_USED_TIMESTAMP)
- .build())
+ .build(),
+ /*logger=*/ null)
.getResults();
assertThat(page).hasSize(2);
assertThat(page.get(0).getGenericDocument().getId()).isEqualTo("id1");
@@ -1499,7 +1522,9 @@ public class AppSearchImplTest {
mTemporaryFolder.newFolder(),
context,
VisibilityStore.NO_OP_USER_ID,
- /*globalQuerierPackage=*/ "");
+ /*globalQuerierPackage=*/ "",
+ /*logger
+ =*/ null);
// Initial check that we could do something at first.
List<AppSearchSchema> schemas =
@@ -1561,7 +1586,8 @@ public class AppSearchImplTest {
"query",
new SearchSpec.Builder()
.setTermMatch(TermMatchType.Code.PREFIX_VALUE)
- .build());
+ .build(),
+ /*logger=*/ null);
});
expectThrows(
@@ -1573,7 +1599,8 @@ public class AppSearchImplTest {
.setTermMatch(TermMatchType.Code.PREFIX_VALUE)
.build(),
"package",
- /*callerUid=*/ 1);
+ /*callerUid=*/ 1,
+ /*logger=*/ null);
});
expectThrows(
@@ -1647,7 +1674,8 @@ public class AppSearchImplTest {
appsearchDir,
context,
VisibilityStore.NO_OP_USER_ID,
- /*globalQuerierPackage=*/ "");
+ /*globalQuerierPackage=*/ "",
+ /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1677,7 +1705,8 @@ public class AppSearchImplTest {
appsearchDir,
context,
VisibilityStore.NO_OP_USER_ID,
- /*globalQuerierPackage=*/ "");
+ /*globalQuerierPackage=*/ "",
+ /*logger=*/ null);
getResult =
appSearchImpl2.getDocument(
"package", "database", "namespace1", "id1", Collections.emptyMap());
@@ -1694,7 +1723,8 @@ public class AppSearchImplTest {
appsearchDir,
context,
VisibilityStore.NO_OP_USER_ID,
- /*globalQuerierPackage=*/ "");
+ /*globalQuerierPackage=*/ "",
+ /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1748,7 +1778,8 @@ public class AppSearchImplTest {
appsearchDir,
context,
VisibilityStore.NO_OP_USER_ID,
- /*globalQuerierPackage=*/ "");
+ /*globalQuerierPackage=*/ "",
+ /*logger=*/ null);
expectThrows(
AppSearchException.class,
() ->
@@ -1774,7 +1805,8 @@ public class AppSearchImplTest {
appsearchDir,
context,
VisibilityStore.NO_OP_USER_ID,
- /*globalQuerierPackage=*/ "");
+ /*globalQuerierPackage=*/ "",
+ /*logger=*/ null);
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1835,7 +1867,8 @@ public class AppSearchImplTest {
appsearchDir,
context,
VisibilityStore.NO_OP_USER_ID,
- /*globalQuerierPackage=*/ "");
+ /*globalQuerierPackage=*/ "",
+ /*logger=*/ null);
expectThrows(
AppSearchException.class,
() ->
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 1194e76ee2b5..5989bb65bd39 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
@@ -23,13 +23,21 @@ import android.annotation.Nullable;
import android.app.appsearch.AppSearchResult;
import android.app.appsearch.AppSearchSchema;
import android.app.appsearch.GenericDocument;
+import android.app.appsearch.SearchResultPage;
+import android.app.appsearch.SearchSpec;
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
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.PutDocumentStats;
+import com.android.server.appsearch.external.localstorage.stats.SearchStats;
+import com.android.server.appsearch.proto.InitializeStatsProto;
import com.android.server.appsearch.proto.PutDocumentStatsProto;
+import com.android.server.appsearch.proto.QueryStatsProto;
+import com.android.server.appsearch.proto.ScoringSpecProto;
+import com.android.server.appsearch.proto.TermMatchType;
import org.junit.Before;
import org.junit.Rule;
@@ -54,23 +62,93 @@ public class AppSearchLoggerTest {
mTemporaryFolder.newFolder(),
context,
VisibilityStore.NO_OP_USER_ID,
- /*globalQuerierPackage=*/ context.getPackageName());
+ /*globalQuerierPackage=*/ context.getPackageName(),
+ /*logger=*/ null);
mLogger = new TestLogger();
}
// Test only not thread safe.
public class TestLogger implements AppSearchLogger {
+ @Nullable CallStats mCallStats;
@Nullable PutDocumentStats mPutDocumentStats;
+ @Nullable InitializeStats mInitializeStats;
+ @Nullable SearchStats mSearchStats;
@Override
public void logStats(@NonNull CallStats stats) {
- throw new UnsupportedOperationException();
+ mCallStats = stats;
}
@Override
public void logStats(@NonNull PutDocumentStats stats) {
mPutDocumentStats = stats;
}
+
+ @Override
+ public void logStats(@NonNull InitializeStats stats) {
+ mInitializeStats = stats;
+ }
+
+ @Override
+ public void logStats(@NonNull SearchStats stats) {
+ mSearchStats = stats;
+ }
+ }
+
+ @Test
+ public void testAppSearchLoggerHelper_testCopyNativeStats_initialize() {
+ int nativeLatencyMillis = 3;
+ int nativeDocumentStoreRecoveryCause = InitializeStatsProto.RecoveryCause.DATA_LOSS_VALUE;
+ int nativeIndexRestorationCause =
+ InitializeStatsProto.RecoveryCause.INCONSISTENT_WITH_GROUND_TRUTH_VALUE;
+ int nativeSchemaStoreRecoveryCause =
+ InitializeStatsProto.RecoveryCause.TOTAL_CHECKSUM_MISMATCH_VALUE;
+ int nativeDocumentStoreRecoveryLatencyMillis = 7;
+ int nativeIndexRestorationLatencyMillis = 8;
+ int nativeSchemaStoreRecoveryLatencyMillis = 9;
+ int nativeDocumentStoreDataStatus =
+ InitializeStatsProto.DocumentStoreDataStatus.NO_DATA_LOSS_VALUE;
+ int nativeNumDocuments = 11;
+ int nativeNumSchemaTypes = 12;
+ InitializeStatsProto.Builder nativeInitBuilder =
+ InitializeStatsProto.newBuilder()
+ .setLatencyMs(nativeLatencyMillis)
+ .setDocumentStoreRecoveryCause(
+ InitializeStatsProto.RecoveryCause.forNumber(
+ nativeDocumentStoreRecoveryCause))
+ .setIndexRestorationCause(
+ InitializeStatsProto.RecoveryCause.forNumber(
+ nativeIndexRestorationCause))
+ .setSchemaStoreRecoveryCause(
+ InitializeStatsProto.RecoveryCause.forNumber(
+ nativeSchemaStoreRecoveryCause))
+ .setDocumentStoreRecoveryLatencyMs(nativeDocumentStoreRecoveryLatencyMillis)
+ .setIndexRestorationLatencyMs(nativeIndexRestorationLatencyMillis)
+ .setSchemaStoreRecoveryLatencyMs(nativeSchemaStoreRecoveryLatencyMillis)
+ .setDocumentStoreDataStatus(
+ InitializeStatsProto.DocumentStoreDataStatus.forNumber(
+ nativeDocumentStoreDataStatus))
+ .setNumDocuments(nativeNumDocuments)
+ .setNumSchemaTypes(nativeNumSchemaTypes);
+ InitializeStats.Builder initBuilder = new InitializeStats.Builder();
+
+ AppSearchLoggerHelper.copyNativeStats(nativeInitBuilder.build(), initBuilder);
+
+ InitializeStats iStats = initBuilder.build();
+ assertThat(iStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+ assertThat(iStats.getDocumentStoreRecoveryCause())
+ .isEqualTo(nativeDocumentStoreRecoveryCause);
+ assertThat(iStats.getIndexRestorationCause()).isEqualTo(nativeIndexRestorationCause);
+ assertThat(iStats.getSchemaStoreRecoveryCause()).isEqualTo(nativeSchemaStoreRecoveryCause);
+ assertThat(iStats.getDocumentStoreRecoveryLatencyMillis())
+ .isEqualTo(nativeDocumentStoreRecoveryLatencyMillis);
+ assertThat(iStats.getIndexRestorationLatencyMillis())
+ .isEqualTo(nativeIndexRestorationLatencyMillis);
+ assertThat(iStats.getSchemaStoreRecoveryLatencyMillis())
+ .isEqualTo(nativeSchemaStoreRecoveryLatencyMillis);
+ assertThat(iStats.getDocumentStoreDataStatus()).isEqualTo(nativeDocumentStoreDataStatus);
+ assertThat(iStats.getDocumentCount()).isEqualTo(nativeNumDocuments);
+ assertThat(iStats.getSchemaTypeCount()).isEqualTo(nativeNumSchemaTypes);
}
@Test
@@ -111,10 +189,97 @@ public class AppSearchLoggerTest {
assertThat(pStats.getNativeExceededMaxNumTokens()).isEqualTo(nativeExceededMaxNumTokens);
}
+ @Test
+ public void testAppSearchLoggerHelper_testCopyNativeStats_search() {
+ int nativeLatencyMillis = 4;
+ int nativeNumTerms = 5;
+ // TODO(b/185804196) query length needs to be added in the native stats.
+ // int nativeQueryLength = 6;
+ int nativeNumNamespacesFiltered = 7;
+ int nativeNumSchemaTypesFiltered = 8;
+ int nativeRequestedPageSize = 9;
+ int nativeNumResultsReturnedCurrentPage = 10;
+ boolean nativeIsFirstPage = true;
+ int nativeParseQueryLatencyMillis = 11;
+ int nativeRankingStrategy = ScoringSpecProto.RankingStrategy.Code.CREATION_TIMESTAMP_VALUE;
+ int nativeNumDocumentsScored = 13;
+ int nativeScoringLatencyMillis = 14;
+ int nativeRankingLatencyMillis = 15;
+ int nativeNumResultsWithSnippets = 16;
+ int nativeDocumentRetrievingLatencyMillis = 17;
+ QueryStatsProto nativeQueryStats =
+ QueryStatsProto.newBuilder()
+ .setLatencyMs(nativeLatencyMillis)
+ .setNumTerms(nativeNumTerms)
+ .setNumNamespacesFiltered(nativeNumNamespacesFiltered)
+ .setNumSchemaTypesFiltered(nativeNumSchemaTypesFiltered)
+ .setRequestedPageSize(nativeRequestedPageSize)
+ .setNumResultsReturnedCurrentPage(nativeNumResultsReturnedCurrentPage)
+ .setIsFirstPage(nativeIsFirstPage)
+ .setParseQueryLatencyMs(nativeParseQueryLatencyMillis)
+ .setRankingStrategy(
+ ScoringSpecProto.RankingStrategy.Code.forNumber(
+ nativeRankingStrategy))
+ .setNumDocumentsScored(nativeNumDocumentsScored)
+ .setScoringLatencyMs(nativeScoringLatencyMillis)
+ .setRankingLatencyMs(nativeRankingLatencyMillis)
+ .setNumResultsWithSnippets(nativeNumResultsWithSnippets)
+ .setDocumentRetrievalLatencyMs(nativeDocumentRetrievingLatencyMillis)
+ .build();
+ SearchStats.Builder qBuilder =
+ new SearchStats.Builder(SearchStats.VISIBILITY_SCOPE_LOCAL, "packageName")
+ .setDatabase("database");
+
+ AppSearchLoggerHelper.copyNativeStats(nativeQueryStats, qBuilder);
+
+ SearchStats sStats = qBuilder.build();
+ assertThat(sStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+ assertThat(sStats.getTermCount()).isEqualTo(nativeNumTerms);
+ // assertThat(sStats.getNativeQueryLength()).isEqualTo(nativeQueryLength);
+ assertThat(sStats.getFilteredNamespaceCount()).isEqualTo(nativeNumNamespacesFiltered);
+ assertThat(sStats.getFilteredSchemaTypeCount()).isEqualTo(nativeNumSchemaTypesFiltered);
+ assertThat(sStats.getRequestedPageSize()).isEqualTo(nativeRequestedPageSize);
+ assertThat(sStats.getCurrentPageReturnedResultCount())
+ .isEqualTo(nativeNumResultsReturnedCurrentPage);
+ assertThat(sStats.isFirstPage()).isTrue();
+ assertThat(sStats.getParseQueryLatencyMillis()).isEqualTo(nativeParseQueryLatencyMillis);
+ assertThat(sStats.getRankingStrategy()).isEqualTo(nativeRankingStrategy);
+ assertThat(sStats.getScoredDocumentCount()).isEqualTo(nativeNumDocumentsScored);
+ assertThat(sStats.getScoringLatencyMillis()).isEqualTo(nativeScoringLatencyMillis);
+ assertThat(sStats.getRankingLatencyMillis()).isEqualTo(nativeRankingLatencyMillis);
+ assertThat(sStats.getResultWithSnippetsCount()).isEqualTo(nativeNumResultsWithSnippets);
+ assertThat(sStats.getDocumentRetrievingLatencyMillis())
+ .isEqualTo(nativeDocumentRetrievingLatencyMillis);
+ }
+
//
// Testing actual logging
//
@Test
+ public void testLoggingStats_initialize() throws Exception {
+ Context context = ApplicationProvider.getApplicationContext();
+
+ AppSearchImpl appSearchImpl =
+ AppSearchImpl.create(
+ mTemporaryFolder.newFolder(),
+ context,
+ VisibilityStore.NO_OP_USER_ID,
+ /*globalQuerierPackage=*/ context.getPackageName(),
+ mLogger);
+
+ InitializeStats iStats = mLogger.mInitializeStats;
+ assertThat(iStats).isNotNull();
+ assertThat(iStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
+ assertThat(iStats.getTotalLatencyMillis()).isGreaterThan(0);
+ assertThat(iStats.hasDeSync()).isFalse();
+ assertThat(iStats.getNativeLatencyMillis()).isGreaterThan(0);
+ assertThat(iStats.getDocumentStoreDataStatus())
+ .isEqualTo(InitializeStatsProto.DocumentStoreDataStatus.NO_DATA_LOSS_VALUE);
+ assertThat(iStats.getDocumentCount()).isEqualTo(0);
+ assertThat(iStats.getSchemaTypeCount()).isEqualTo(0);
+ }
+
+ @Test
public void testLoggingStats_putDocument() throws Exception {
// Insert schema
final String testPackageName = "testPackage";
@@ -141,4 +306,53 @@ public class AppSearchLoggerTest {
// The rest of native stats have been tested in testCopyNativeStats
assertThat(pStats.getNativeDocumentSizeBytes()).isGreaterThan(0);
}
+
+ @Test
+ public void testLoggingStats_search() throws Exception {
+ // Insert schema
+ final String testPackageName = "testPackage";
+ final String testDatabase = "testDatabase";
+ List<AppSearchSchema> schemas =
+ Collections.singletonList(new AppSearchSchema.Builder("type").build());
+ mAppSearchImpl.setSchema(
+ testPackageName,
+ testDatabase,
+ schemas,
+ /*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
+ /*schemasPackageAccessible=*/ Collections.emptyMap(),
+ /*forceOverride=*/ false,
+ /*version=*/ 0);
+ GenericDocument document = new GenericDocument.Builder<>("namespace", "id", "type").build();
+ mAppSearchImpl.putDocument(testPackageName, testDatabase, document, mLogger);
+
+ // No query filters specified. package2 should only get its own documents back.
+ SearchSpec searchSpec =
+ new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
+ SearchResultPage searchResultPage =
+ mAppSearchImpl.query(
+ testPackageName,
+ testDatabase,
+ /*QueryExpression=*/ "",
+ searchSpec,
+ /*logger=*/ mLogger);
+
+ assertThat(searchResultPage.getResults()).hasSize(1);
+ assertThat(searchResultPage.getResults().get(0).getGenericDocument()).isEqualTo(document);
+
+ SearchStats sStats = mLogger.mSearchStats;
+
+ assertThat(sStats).isNotNull();
+ assertThat(sStats.getPackageName()).isEqualTo(testPackageName);
+ assertThat(sStats.getDatabase()).isEqualTo(testDatabase);
+ assertThat(sStats.getStatusCode()).isEqualTo(AppSearchResult.RESULT_OK);
+ assertThat(sStats.getTotalLatencyMillis()).isGreaterThan(0);
+ assertThat(sStats.getVisibilityScope()).isEqualTo(SearchStats.VISIBILITY_SCOPE_LOCAL);
+ assertThat(sStats.getTermCount()).isEqualTo(0);
+ // assertThat(sStats.getNativeQueryLength()).isEqualTo(0);
+ assertThat(sStats.getFilteredNamespaceCount()).isEqualTo(1);
+ assertThat(sStats.getFilteredSchemaTypeCount()).isEqualTo(1);
+ assertThat(sStats.getCurrentPageReturnedResultCount()).isEqualTo(1);
+ assertThat(sStats.isFirstPage()).isTrue();
+ assertThat(sStats.getScoredDocumentCount()).isEqualTo(1);
+ }
}
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 8dbf249c4e96..5c7ccfc458b2 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
@@ -134,4 +134,135 @@ public class AppSearchStatsTest {
assertThat(pStats.getNativeNumTokensIndexed()).isEqualTo(nativeNumTokensIndexed);
assertThat(pStats.getNativeExceededMaxNumTokens()).isEqualTo(nativeExceededMaxNumTokens);
}
+
+ @Test
+ public void testAppSearchStats_InitializeStats() {
+ int prepareSchemaAndNamespacesLatencyMillis = 1;
+ int prepareVisibilityFileLatencyMillis = 2;
+ int nativeLatencyMillis = 3;
+ int nativeDocumentStoreRecoveryCause = 4;
+ int nativeIndexRestorationCause = 5;
+ int nativeSchemaStoreRecoveryCause = 6;
+ int nativeDocumentStoreRecoveryLatencyMillis = 7;
+ int nativeIndexRestorationLatencyMillis = 8;
+ int nativeSchemaStoreRecoveryLatencyMillis = 9;
+ int nativeDocumentStoreDataStatus = 10;
+ int nativeNumDocuments = 11;
+ int nativeNumSchemaTypes = 12;
+
+ final InitializeStats.Builder iStatsBuilder =
+ new InitializeStats.Builder()
+ .setStatusCode(TEST_STATUS_CODE)
+ .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS)
+ .setHasDeSync(/* hasDeSyncs= */ true)
+ .setPrepareSchemaAndNamespacesLatencyMillis(
+ prepareSchemaAndNamespacesLatencyMillis)
+ .setPrepareVisibilityStoreLatencyMillis(prepareVisibilityFileLatencyMillis)
+ .setNativeLatencyMillis(nativeLatencyMillis)
+ .setDocumentStoreRecoveryCause(nativeDocumentStoreRecoveryCause)
+ .setIndexRestorationCause(nativeIndexRestorationCause)
+ .setSchemaStoreRecoveryCause(nativeSchemaStoreRecoveryCause)
+ .setDocumentStoreRecoveryLatencyMillis(
+ nativeDocumentStoreRecoveryLatencyMillis)
+ .setIndexRestorationLatencyMillis(nativeIndexRestorationLatencyMillis)
+ .setSchemaStoreRecoveryLatencyMillis(nativeSchemaStoreRecoveryLatencyMillis)
+ .setDocumentStoreDataStatus(nativeDocumentStoreDataStatus)
+ .setDocumentCount(nativeNumDocuments)
+ .setSchemaTypeCount(nativeNumSchemaTypes);
+ final InitializeStats iStats = iStatsBuilder.build();
+
+ assertThat(iStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE);
+ assertThat(iStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS);
+ assertThat(iStats.hasDeSync()).isTrue();
+ assertThat(iStats.getPrepareSchemaAndNamespacesLatencyMillis())
+ .isEqualTo(prepareSchemaAndNamespacesLatencyMillis);
+ assertThat(iStats.getPrepareVisibilityStoreLatencyMillis())
+ .isEqualTo(prepareVisibilityFileLatencyMillis);
+ assertThat(iStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+ assertThat(iStats.getDocumentStoreRecoveryCause())
+ .isEqualTo(nativeDocumentStoreRecoveryCause);
+ assertThat(iStats.getIndexRestorationCause()).isEqualTo(nativeIndexRestorationCause);
+ assertThat(iStats.getSchemaStoreRecoveryCause()).isEqualTo(nativeSchemaStoreRecoveryCause);
+ assertThat(iStats.getDocumentStoreRecoveryLatencyMillis())
+ .isEqualTo(nativeDocumentStoreRecoveryLatencyMillis);
+ assertThat(iStats.getIndexRestorationLatencyMillis())
+ .isEqualTo(nativeIndexRestorationLatencyMillis);
+ assertThat(iStats.getSchemaStoreRecoveryLatencyMillis())
+ .isEqualTo(nativeSchemaStoreRecoveryLatencyMillis);
+ assertThat(iStats.getDocumentStoreDataStatus()).isEqualTo(nativeDocumentStoreDataStatus);
+ assertThat(iStats.getDocumentCount()).isEqualTo(nativeNumDocuments);
+ assertThat(iStats.getSchemaTypeCount()).isEqualTo(nativeNumSchemaTypes);
+ }
+
+ @Test
+ public void testAppSearchStats_SearchStats() {
+ int rewriteSearchSpecLatencyMillis = 1;
+ int rewriteSearchResultLatencyMillis = 2;
+ int visibilityScope = SearchStats.VISIBILITY_SCOPE_LOCAL;
+ int nativeLatencyMillis = 4;
+ int nativeNumTerms = 5;
+ int nativeQueryLength = 6;
+ int nativeNumNamespacesFiltered = 7;
+ int nativeNumSchemaTypesFiltered = 8;
+ int nativeRequestedPageSize = 9;
+ int nativeNumResultsReturnedCurrentPage = 10;
+ boolean nativeIsFirstPage = true;
+ int nativeParseQueryLatencyMillis = 11;
+ int nativeRankingStrategy = 12;
+ int nativeNumDocumentsScored = 13;
+ int nativeScoringLatencyMillis = 14;
+ int nativeRankingLatencyMillis = 15;
+ int nativeNumResultsSnippeted = 16;
+ int nativeDocumentRetrievingLatencyMillis = 17;
+ final SearchStats.Builder sStatsBuilder =
+ new SearchStats.Builder(visibilityScope, TEST_PACKAGE_NAME)
+ .setDatabase(TEST_DATA_BASE)
+ .setStatusCode(TEST_STATUS_CODE)
+ .setTotalLatencyMillis(TEST_TOTAL_LATENCY_MILLIS)
+ .setRewriteSearchSpecLatencyMillis(rewriteSearchSpecLatencyMillis)
+ .setRewriteSearchResultLatencyMillis(rewriteSearchResultLatencyMillis)
+ .setNativeLatencyMillis(nativeLatencyMillis)
+ .setTermCount(nativeNumTerms)
+ .setQueryLength(nativeQueryLength)
+ .setFilteredNamespaceCount(nativeNumNamespacesFiltered)
+ .setFilteredSchemaTypeCount(nativeNumSchemaTypesFiltered)
+ .setRequestedPageSize(nativeRequestedPageSize)
+ .setCurrentPageReturnedResultCount(nativeNumResultsReturnedCurrentPage)
+ .setIsFirstPage(nativeIsFirstPage)
+ .setParseQueryLatencyMillis(nativeParseQueryLatencyMillis)
+ .setRankingStrategy(nativeRankingStrategy)
+ .setScoredDocumentCount(nativeNumDocumentsScored)
+ .setScoringLatencyMillis(nativeScoringLatencyMillis)
+ .setRankingLatencyMillis(nativeRankingLatencyMillis)
+ .setResultWithSnippetsCount(nativeNumResultsSnippeted)
+ .setDocumentRetrievingLatencyMillis(nativeDocumentRetrievingLatencyMillis);
+ final SearchStats sStats = sStatsBuilder.build();
+
+ assertThat(sStats.getPackageName()).isEqualTo(TEST_PACKAGE_NAME);
+ assertThat(sStats.getDatabase()).isEqualTo(TEST_DATA_BASE);
+ assertThat(sStats.getStatusCode()).isEqualTo(TEST_STATUS_CODE);
+ assertThat(sStats.getTotalLatencyMillis()).isEqualTo(TEST_TOTAL_LATENCY_MILLIS);
+ assertThat(sStats.getRewriteSearchSpecLatencyMillis())
+ .isEqualTo(rewriteSearchSpecLatencyMillis);
+ assertThat(sStats.getRewriteSearchResultLatencyMillis())
+ .isEqualTo(rewriteSearchResultLatencyMillis);
+ assertThat(sStats.getVisibilityScope()).isEqualTo(visibilityScope);
+ assertThat(sStats.getNativeLatencyMillis()).isEqualTo(nativeLatencyMillis);
+ assertThat(sStats.getTermCount()).isEqualTo(nativeNumTerms);
+ assertThat(sStats.getQueryLength()).isEqualTo(nativeQueryLength);
+ assertThat(sStats.getFilteredNamespaceCount()).isEqualTo(nativeNumNamespacesFiltered);
+ assertThat(sStats.getFilteredSchemaTypeCount()).isEqualTo(nativeNumSchemaTypesFiltered);
+ assertThat(sStats.getRequestedPageSize()).isEqualTo(nativeRequestedPageSize);
+ assertThat(sStats.getCurrentPageReturnedResultCount())
+ .isEqualTo(nativeNumResultsReturnedCurrentPage);
+ assertThat(sStats.isFirstPage()).isTrue();
+ assertThat(sStats.getParseQueryLatencyMillis()).isEqualTo(nativeParseQueryLatencyMillis);
+ assertThat(sStats.getRankingStrategy()).isEqualTo(nativeRankingStrategy);
+ assertThat(sStats.getScoredDocumentCount()).isEqualTo(nativeNumDocumentsScored);
+ assertThat(sStats.getScoringLatencyMillis()).isEqualTo(nativeScoringLatencyMillis);
+ assertThat(sStats.getRankingLatencyMillis()).isEqualTo(nativeRankingLatencyMillis);
+ assertThat(sStats.getResultWithSnippetsCount()).isEqualTo(nativeNumResultsSnippeted);
+ assertThat(sStats.getDocumentRetrievingLatencyMillis())
+ .isEqualTo(nativeDocumentRetrievingLatencyMillis);
+ }
}