Merge "Update framework from jetpack." into sc-dev

This commit is contained in:
Alexander Dorokhine
2021-04-28 03:33:15 +00:00
committed by Android (Google) Code Review
16 changed files with 1547 additions and 59 deletions

View File

@@ -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
*/

View File

@@ -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,

View File

@@ -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(

View File

@@ -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);
}
/**

View File

@@ -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;
}
/**

View File

@@ -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.
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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.
*

View File

@@ -1 +1 @@
I06df2c636d26419e653c5d8c9e7d15449da6816e
I19dac52031c47099f621eced9f148931f1021f25

View File

@@ -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);
}

View File

@@ -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,

View File

@@ -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,
() ->

View File

@@ -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,9 +189,96 @@ 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
@@ -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);
}
}

View File

@@ -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);
}
}