1 /* 2 * Copyright 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.server.appsearch.external.localstorage.stats; 17 18 import android.annotation.IntDef; 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.app.appsearch.AppSearchResult; 22 import android.app.appsearch.SearchSpec; 23 24 import com.android.internal.util.Preconditions; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.util.Objects; 29 30 /** 31 * Class holds detailed stats for {@link android.app.appsearch.AppSearchSession#search(String, 32 * SearchSpec)} 33 * 34 * @hide 35 */ 36 public final class SearchStats { 37 @IntDef( 38 value = { 39 // Searches apps' own documents. 40 VISIBILITY_SCOPE_LOCAL, 41 // Searches the global documents. Including platform surfaceable and 3p-access. 42 VISIBILITY_SCOPE_GLOBAL, 43 VISIBILITY_SCOPE_UNKNOWN, 44 // TODO(b/173532925) Add THIRD_PARTY_ACCESS once we can distinguish platform 45 // surfaceable from 3p access(right both of them are categorized as 46 // VISIBILITY_SCOPE_GLOBAL) 47 }) 48 @Retention(RetentionPolicy.SOURCE) 49 public @interface VisibilityScope {} 50 51 // Searches apps' own documents. 52 public static final int VISIBILITY_SCOPE_LOCAL = 1; 53 // Searches the global documents. Including platform surfaceable and 3p-access. 54 public static final int VISIBILITY_SCOPE_GLOBAL = 2; 55 public static final int VISIBILITY_SCOPE_UNKNOWN = 3; 56 57 // TODO(b/173532925): Add a field searchType to indicate where the search is used(normal 58 // query vs in removeByQuery vs during migration) 59 60 @NonNull private final String mPackageName; 61 @Nullable private final String mDatabase; 62 /** 63 * The status code returned by {@link AppSearchResult#getResultCode()} for the call or internal 64 * state. 65 */ 66 @AppSearchResult.ResultCode private final int mStatusCode; 67 68 private final int mTotalLatencyMillis; 69 /** Time used to rewrite the search spec. */ 70 private final int mRewriteSearchSpecLatencyMillis; 71 /** Time used to rewrite the search results. */ 72 private final int mRewriteSearchResultLatencyMillis; 73 /** Defines the scope the query is searching over */ 74 @VisibilityScope private final int mVisibilityScope; 75 /** Overall time used for the native function call. */ 76 private final int mNativeLatencyMillis; 77 /** Number of terms in the query string. */ 78 private final int mNativeNumTerms; 79 /** Length of the query string. */ 80 private final int mNativeQueryLength; 81 /** Number of namespaces filtered. */ 82 private final int mNativeNumNamespacesFiltered; 83 /** Number of schema types filtered. */ 84 private final int mNativeNumSchemaTypesFiltered; 85 /** The requested number of results in one page. */ 86 private final int mNativeRequestedPageSize; 87 /** The actual number of results returned in the current page. */ 88 private final int mNativeNumResultsReturnedCurrentPage; 89 /** 90 * Whether the function call is querying the first page. If it's not, Icing will fetch the 91 * results from cache so that some steps may be skipped. 92 */ 93 private final boolean mNativeIsFirstPage; 94 /** 95 * Time used to parse the query, including 2 parts: tokenizing and transforming tokens into an 96 * iterator tree. 97 */ 98 private final int mNativeParseQueryLatencyMillis; 99 /** Strategy of scoring and ranking. */ 100 @SearchSpec.RankingStrategy private final int mNativeRankingStrategy; 101 /** Number of documents scored. */ 102 private final int mNativeNumDocumentsScored; 103 /** Time used to score the raw results. */ 104 private final int mNativeScoringLatencyMillis; 105 /** Time used to rank the scored results. */ 106 private final int mNativeRankingLatencyMillis; 107 /** 108 * Time used to fetch the document protos. Note that it includes the time to snippet if {@link 109 * SearchStats#mNativeNumResultsWithSnippets} is greater than 0. 110 */ 111 private final int mNativeDocumentRetrievingLatencyMillis; 112 /** How many snippets are calculated. */ 113 private final int mNativeNumResultsWithSnippets; 114 SearchStats(@onNull Builder builder)115 SearchStats(@NonNull Builder builder) { 116 Objects.requireNonNull(builder); 117 mPackageName = builder.mPackageName; 118 mDatabase = builder.mDatabase; 119 mStatusCode = builder.mStatusCode; 120 mTotalLatencyMillis = builder.mTotalLatencyMillis; 121 mRewriteSearchSpecLatencyMillis = builder.mRewriteSearchSpecLatencyMillis; 122 mRewriteSearchResultLatencyMillis = builder.mRewriteSearchResultLatencyMillis; 123 mVisibilityScope = builder.mVisibilityScope; 124 mNativeLatencyMillis = builder.mNativeLatencyMillis; 125 mNativeNumTerms = builder.mNativeNumTerms; 126 mNativeQueryLength = builder.mNativeQueryLength; 127 mNativeNumNamespacesFiltered = builder.mNativeNumNamespacesFiltered; 128 mNativeNumSchemaTypesFiltered = builder.mNativeNumSchemaTypesFiltered; 129 mNativeRequestedPageSize = builder.mNativeRequestedPageSize; 130 mNativeNumResultsReturnedCurrentPage = builder.mNativeNumResultsReturnedCurrentPage; 131 mNativeIsFirstPage = builder.mNativeIsFirstPage; 132 mNativeParseQueryLatencyMillis = builder.mNativeParseQueryLatencyMillis; 133 mNativeRankingStrategy = builder.mNativeRankingStrategy; 134 mNativeNumDocumentsScored = builder.mNativeNumDocumentsScored; 135 mNativeScoringLatencyMillis = builder.mNativeScoringLatencyMillis; 136 mNativeRankingLatencyMillis = builder.mNativeRankingLatencyMillis; 137 mNativeNumResultsWithSnippets = builder.mNativeNumResultsWithSnippets; 138 mNativeDocumentRetrievingLatencyMillis = builder.mNativeDocumentRetrievingLatencyMillis; 139 } 140 141 /** Returns the package name of the session. */ 142 @NonNull getPackageName()143 public String getPackageName() { 144 return mPackageName; 145 } 146 147 /** 148 * Returns the database name of the session. 149 * 150 * @return database name used by the session. {@code null} if and only if it is a global 151 * search(visibilityScope is {@link SearchStats#VISIBILITY_SCOPE_GLOBAL}). 152 */ 153 @Nullable getDatabase()154 public String getDatabase() { 155 return mDatabase; 156 } 157 158 /** Returns status of the search. */ 159 @AppSearchResult.ResultCode getStatusCode()160 public int getStatusCode() { 161 return mStatusCode; 162 } 163 164 /** Returns the total latency of the search. */ getTotalLatencyMillis()165 public int getTotalLatencyMillis() { 166 return mTotalLatencyMillis; 167 } 168 169 /** Returns how much time spent on rewriting the {@link SearchSpec}. */ getRewriteSearchSpecLatencyMillis()170 public int getRewriteSearchSpecLatencyMillis() { 171 return mRewriteSearchSpecLatencyMillis; 172 } 173 174 /** Returns how much time spent on rewriting the {@link android.app.appsearch.SearchResult}. */ getRewriteSearchResultLatencyMillis()175 public int getRewriteSearchResultLatencyMillis() { 176 return mRewriteSearchResultLatencyMillis; 177 } 178 179 /** Returns the visibility scope of the search. */ 180 @VisibilityScope getVisibilityScope()181 public int getVisibilityScope() { 182 return mVisibilityScope; 183 } 184 185 /** Returns how much time spent on the native calls. */ getNativeLatencyMillis()186 public int getNativeLatencyMillis() { 187 return mNativeLatencyMillis; 188 } 189 190 /** Returns number of terms in the search string. */ getTermCount()191 public int getTermCount() { 192 return mNativeNumTerms; 193 } 194 195 /** Returns the length of the search string. */ getQueryLength()196 public int getQueryLength() { 197 return mNativeQueryLength; 198 } 199 200 /** Returns number of namespaces filtered. */ getFilteredNamespaceCount()201 public int getFilteredNamespaceCount() { 202 return mNativeNumNamespacesFiltered; 203 } 204 205 /** Returns number of schema types filtered. */ getFilteredSchemaTypeCount()206 public int getFilteredSchemaTypeCount() { 207 return mNativeNumSchemaTypesFiltered; 208 } 209 210 /** Returns the requested number of results in one page. */ getRequestedPageSize()211 public int getRequestedPageSize() { 212 return mNativeRequestedPageSize; 213 } 214 215 /** Returns the actual number of results returned in the current page. */ getCurrentPageReturnedResultCount()216 public int getCurrentPageReturnedResultCount() { 217 return mNativeNumResultsReturnedCurrentPage; 218 } 219 220 // TODO(b/185184738) Make it an integer to show how many pages having been returned. 221 /** Returns whether the function call is querying the first page. */ isFirstPage()222 public boolean isFirstPage() { 223 return mNativeIsFirstPage; 224 } 225 226 /** 227 * Returns time used to parse the query, including 2 parts: tokenizing and transforming tokens 228 * into an iterator tree. 229 */ getParseQueryLatencyMillis()230 public int getParseQueryLatencyMillis() { 231 return mNativeParseQueryLatencyMillis; 232 } 233 234 /** Returns strategy of scoring and ranking. */ 235 @SearchSpec.RankingStrategy getRankingStrategy()236 public int getRankingStrategy() { 237 return mNativeRankingStrategy; 238 } 239 240 /** Returns number of documents scored. */ getScoredDocumentCount()241 public int getScoredDocumentCount() { 242 return mNativeNumDocumentsScored; 243 } 244 245 /** Returns time used to score the raw results. */ getScoringLatencyMillis()246 public int getScoringLatencyMillis() { 247 return mNativeScoringLatencyMillis; 248 } 249 250 /** Returns time used to rank the scored results. */ getRankingLatencyMillis()251 public int getRankingLatencyMillis() { 252 return mNativeRankingLatencyMillis; 253 } 254 255 /** 256 * Returns time used to fetch the document protos. Note that it includes the time to snippet if 257 * {@link SearchStats#mNativeNumResultsWithSnippets} is not zero. 258 */ getDocumentRetrievingLatencyMillis()259 public int getDocumentRetrievingLatencyMillis() { 260 return mNativeDocumentRetrievingLatencyMillis; 261 } 262 263 /** Returns the number of the results in the page returned were snippeted. */ getResultWithSnippetsCount()264 public int getResultWithSnippetsCount() { 265 return mNativeNumResultsWithSnippets; 266 } 267 268 /** Builder for {@link SearchStats} */ 269 public static class Builder { 270 @NonNull final String mPackageName; 271 @Nullable String mDatabase; 272 @AppSearchResult.ResultCode int mStatusCode; 273 int mTotalLatencyMillis; 274 int mRewriteSearchSpecLatencyMillis; 275 int mRewriteSearchResultLatencyMillis; 276 int mVisibilityScope; 277 int mNativeLatencyMillis; 278 int mNativeNumTerms; 279 int mNativeQueryLength; 280 int mNativeNumNamespacesFiltered; 281 int mNativeNumSchemaTypesFiltered; 282 int mNativeRequestedPageSize; 283 int mNativeNumResultsReturnedCurrentPage; 284 boolean mNativeIsFirstPage; 285 int mNativeParseQueryLatencyMillis; 286 int mNativeRankingStrategy; 287 int mNativeNumDocumentsScored; 288 int mNativeScoringLatencyMillis; 289 int mNativeRankingLatencyMillis; 290 int mNativeNumResultsWithSnippets; 291 int mNativeDocumentRetrievingLatencyMillis; 292 293 /** 294 * Constructor 295 * 296 * @param visibilityScope scope for the corresponding search. 297 * @param packageName name of the calling package. 298 */ Builder(@isibilityScope int visibilityScope, @NonNull String packageName)299 public Builder(@VisibilityScope int visibilityScope, @NonNull String packageName) { 300 mVisibilityScope = visibilityScope; 301 mPackageName = Objects.requireNonNull(packageName); 302 } 303 304 /** Sets the database used by the session. */ 305 @NonNull setDatabase(@onNull String database)306 public Builder setDatabase(@NonNull String database) { 307 mDatabase = Objects.requireNonNull(database); 308 return this; 309 } 310 311 /** Sets the status of the search. */ 312 @NonNull setStatusCode(@ppSearchResult.ResultCode int statusCode)313 public Builder setStatusCode(@AppSearchResult.ResultCode int statusCode) { 314 mStatusCode = statusCode; 315 return this; 316 } 317 318 /** Sets total latency for the search. */ 319 @NonNull setTotalLatencyMillis(int totalLatencyMillis)320 public Builder setTotalLatencyMillis(int totalLatencyMillis) { 321 mTotalLatencyMillis = totalLatencyMillis; 322 return this; 323 } 324 325 /** Sets time used to rewrite the search spec. */ 326 @NonNull setRewriteSearchSpecLatencyMillis(int rewriteSearchSpecLatencyMillis)327 public Builder setRewriteSearchSpecLatencyMillis(int rewriteSearchSpecLatencyMillis) { 328 mRewriteSearchSpecLatencyMillis = rewriteSearchSpecLatencyMillis; 329 return this; 330 } 331 332 /** Sets time used to rewrite the search results. */ 333 @NonNull setRewriteSearchResultLatencyMillis(int rewriteSearchResultLatencyMillis)334 public Builder setRewriteSearchResultLatencyMillis(int rewriteSearchResultLatencyMillis) { 335 mRewriteSearchResultLatencyMillis = rewriteSearchResultLatencyMillis; 336 return this; 337 } 338 339 /** Sets overall time used for the native function calls. */ 340 @NonNull setNativeLatencyMillis(int nativeLatencyMillis)341 public Builder setNativeLatencyMillis(int nativeLatencyMillis) { 342 mNativeLatencyMillis = nativeLatencyMillis; 343 return this; 344 } 345 346 /** Sets number of terms in the search string. */ 347 @NonNull setTermCount(int termCount)348 public Builder setTermCount(int termCount) { 349 mNativeNumTerms = termCount; 350 return this; 351 } 352 353 /** Sets length of the search string. */ 354 @NonNull setQueryLength(int queryLength)355 public Builder setQueryLength(int queryLength) { 356 mNativeQueryLength = queryLength; 357 return this; 358 } 359 360 /** Sets number of namespaces filtered. */ 361 @NonNull setFilteredNamespaceCount(int filteredNamespaceCount)362 public Builder setFilteredNamespaceCount(int filteredNamespaceCount) { 363 mNativeNumNamespacesFiltered = filteredNamespaceCount; 364 return this; 365 } 366 367 /** Sets number of schema types filtered. */ 368 @NonNull setFilteredSchemaTypeCount(int filteredSchemaTypeCount)369 public Builder setFilteredSchemaTypeCount(int filteredSchemaTypeCount) { 370 mNativeNumSchemaTypesFiltered = filteredSchemaTypeCount; 371 return this; 372 } 373 374 /** Sets the requested number of results in one page. */ 375 @NonNull setRequestedPageSize(int requestedPageSize)376 public Builder setRequestedPageSize(int requestedPageSize) { 377 mNativeRequestedPageSize = requestedPageSize; 378 return this; 379 } 380 381 /** Sets the actual number of results returned in the current page. */ 382 @NonNull setCurrentPageReturnedResultCount(int currentPageReturnedResultCount)383 public Builder setCurrentPageReturnedResultCount(int currentPageReturnedResultCount) { 384 mNativeNumResultsReturnedCurrentPage = currentPageReturnedResultCount; 385 return this; 386 } 387 388 /** 389 * Sets whether the function call is querying the first page. If it's not, Icing will fetch 390 * the results from cache so that some steps may be skipped. 391 */ 392 @NonNull setIsFirstPage(boolean nativeIsFirstPage)393 public Builder setIsFirstPage(boolean nativeIsFirstPage) { 394 mNativeIsFirstPage = nativeIsFirstPage; 395 return this; 396 } 397 398 /** 399 * Sets time used to parse the query, including 2 parts: tokenizing and transforming tokens 400 * into an iterator tree. 401 */ 402 @NonNull setParseQueryLatencyMillis(int parseQueryLatencyMillis)403 public Builder setParseQueryLatencyMillis(int parseQueryLatencyMillis) { 404 mNativeParseQueryLatencyMillis = parseQueryLatencyMillis; 405 return this; 406 } 407 408 /** Sets strategy of scoring and ranking. */ 409 @NonNull setRankingStrategy(@earchSpec.RankingStrategy int rankingStrategy)410 public Builder setRankingStrategy(@SearchSpec.RankingStrategy int rankingStrategy) { 411 mNativeRankingStrategy = rankingStrategy; 412 return this; 413 } 414 415 /** Sets number of documents scored. */ 416 @NonNull setScoredDocumentCount(int scoredDocumentCount)417 public Builder setScoredDocumentCount(int scoredDocumentCount) { 418 mNativeNumDocumentsScored = scoredDocumentCount; 419 return this; 420 } 421 422 /** Sets time used to score the raw results. */ 423 @NonNull setScoringLatencyMillis(int scoringLatencyMillis)424 public Builder setScoringLatencyMillis(int scoringLatencyMillis) { 425 mNativeScoringLatencyMillis = scoringLatencyMillis; 426 return this; 427 } 428 429 /** Sets time used to rank the scored results. */ 430 @NonNull setRankingLatencyMillis(int rankingLatencyMillis)431 public Builder setRankingLatencyMillis(int rankingLatencyMillis) { 432 mNativeRankingLatencyMillis = rankingLatencyMillis; 433 return this; 434 } 435 436 /** Sets time used to fetch the document protos. */ 437 @NonNull setDocumentRetrievingLatencyMillis(int documentRetrievingLatencyMillis)438 public Builder setDocumentRetrievingLatencyMillis(int documentRetrievingLatencyMillis) { 439 mNativeDocumentRetrievingLatencyMillis = documentRetrievingLatencyMillis; 440 return this; 441 } 442 443 /** Sets how many snippets are calculated. */ 444 @NonNull setResultWithSnippetsCount(int resultWithSnippetsCount)445 public Builder setResultWithSnippetsCount(int resultWithSnippetsCount) { 446 mNativeNumResultsWithSnippets = resultWithSnippetsCount; 447 return this; 448 } 449 450 /** 451 * Constructs a new {@link SearchStats} from the contents of this {@link 452 * SearchStats.Builder}. 453 */ 454 @NonNull build()455 public SearchStats build() { 456 if (mDatabase == null) { 457 Preconditions.checkState( 458 mVisibilityScope != SearchStats.VISIBILITY_SCOPE_LOCAL, 459 "database can not be null if visibilityScope is local."); 460 } 461 462 return new SearchStats(/* builder= */ this); 463 } 464 } 465 } 466