1 /*
2  * Copyright 2023 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 
17 package com.android.server.appsearch.external.localstorage;
18 
19 import android.app.appsearch.SearchSpec;
20 
21 import com.google.android.icing.proto.IcingSearchEngineOptions;
22 
23 /**
24  * An interface exposing the optional config flags in {@link IcingSearchEngineOptions} used to
25  * instantiate {@link com.google.android.icing.IcingSearchEngine}, as well as other additional
26  * config flags for IcingSearchEngine.
27  */
28 public interface IcingOptionsConfig {
29     // Defaults from IcingSearchEngineOptions proto
30     int DEFAULT_MAX_TOKEN_LENGTH = 30;
31 
32     int DEFAULT_INDEX_MERGE_SIZE = 1048576; // 1 MiB
33 
34     boolean DEFAULT_DOCUMENT_STORE_NAMESPACE_ID_FINGERPRINT = false;
35 
36     float DEFAULT_OPTIMIZE_REBUILD_INDEX_THRESHOLD = 0.9f;
37 
38     /**
39      * The default compression level in IcingSearchEngineOptions proto matches the
40      * previously-hardcoded document compression level in Icing (which is 3).
41      */
42     int DEFAULT_COMPRESSION_LEVEL = 3;
43 
44     boolean DEFAULT_USE_PREMAPPING_WITH_FILE_BACKED_VECTOR = false;
45 
46     boolean DEFAULT_USE_PERSISTENT_HASH_MAP = false;
47 
48     int DEFAULT_MAX_PAGE_BYTES_LIMIT = Integer.MAX_VALUE;
49 
50     /**
51      * The default threshold for integer index bucket split. 65536 is picked based on benchmark
52      * (Icing integer-index-storage_benchmark.cc).
53      *
54      * <ul>
55      *   <li>There will be only 16 buckets when indexing 1M integers, which improves the performance
56      *       of numeric search range query.
57      *   <li>It also increases # of hits to read for numeric search exact query, but the overall
58      *       query latency is still reasonable.
59      * </ul>
60      */
61     int DEFAULT_INTEGER_INDEX_BUCKET_SPLIT_THRESHOLD = 65536;
62 
63     boolean DEFAULT_LITE_INDEX_SORT_AT_INDEXING = true;
64 
65     /**
66      * The default sort threshold for the lite index when sort at indexing is enabled. 8192 is
67      * picked based on Icing microbenchmarks (icing-search-engine_benchmarks.cc).
68      */
69     int DEFAULT_LITE_INDEX_SORT_SIZE = 8192; // 8Kib
70 
71     boolean DEFAULT_USE_NEW_QUALIFIED_ID_JOIN_INDEX = false;
72 
73     boolean DEFAULT_BUILD_PROPERTY_EXISTENCE_METADATA_HITS = false;
74 
75     /**
76      * The maximum allowable token length. All tokens in excess of this size will be truncated to
77      * max_token_length before being indexed.
78      *
79      * <p>Clients may use this option to prevent unnecessary indexing of long tokens. Depending on
80      * the use case, indexing all of 'Supercalifragilisticexpialidocious' may be unnecessary - a
81      * user is unlikely to type that entire query. So only indexing the first n bytes may still
82      * provide the desired behavior without wasting resources.
83      */
getMaxTokenLength()84     int getMaxTokenLength();
85 
86     /**
87      * The size (measured in bytes) at which Icing's internal indices should be merged. Icing
88      * buffers changes together before merging them into a more compact format. When the buffer
89      * exceeds index_merge_size during a Put operation, the buffer is merged into the larger, more
90      * compact index.
91      *
92      * <p>This more compact index is more efficient to search over as the index grows larger and has
93      * smaller system health impact.
94      *
95      * <p>Setting a low index_merge_size increases the frequency of merges - increasing
96      * indexing-time latency and flash wear. Setting a high index_merge_size leads to larger
97      * resource usage and higher query latency.
98      */
getIndexMergeSize()99     int getIndexMergeSize();
100 
101     /**
102      * Whether to use namespace id or namespace name to build up fingerprint for
103      * document_key_mapper_ and corpus_mapper_ in document store.
104      */
getDocumentStoreNamespaceIdFingerprint()105     boolean getDocumentStoreNamespaceIdFingerprint();
106 
107     /**
108      * The threshold of the percentage of invalid documents at which to rebuild index during
109      * optimize.
110      *
111      * <p>We rebuild index if and only if |invalid_documents| / |all_documents| >= threshold.
112      *
113      * <p>Rebuilding the index could be faster than optimizing the index if we have removed most of
114      * the documents. Based on benchmarks, 85%~95% seems to be a good threshold for most cases.
115      */
getOptimizeRebuildIndexThreshold()116     float getOptimizeRebuildIndexThreshold();
117 
118     /**
119      * The level of gzip compression for documents in the Icing document store.
120      *
121      * <p>NO_COMPRESSION = 0, BEST_SPEED = 1, BEST_COMPRESSION = 9
122      */
getCompressionLevel()123     int getCompressionLevel();
124 
125     /**
126      * Whether to allow circular references between schema types for the schema definition.
127      *
128      * <p>Even when set to true, circular references are still not allowed in the following cases:
129      * 1. All edges of a cycle have index_nested_properties=true 2. One of the types in the cycle
130      * has a joinable property, or depends on a type with a joinable property.
131      */
getAllowCircularSchemaDefinitions()132     boolean getAllowCircularSchemaDefinitions();
133 
134     /**
135      * Flag for {@link com.google.android.icing.proto.SearchSpecProto}.
136      *
137      * <p>Whether to use the read-only implementation of IcingSearchEngine::Search.
138      *
139      * <p>The read-only version enables multiple queries to be performed concurrently as it only
140      * acquires the read lock at IcingSearchEngine's level. Finer-grained locks are implemented
141      * around code paths that write changes to Icing during Search.
142      */
getUseReadOnlySearch()143     boolean getUseReadOnlySearch();
144 
145     /**
146      * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}.
147      *
148      * <p>Whether or not to pre-map the potential memory region used by the PersistentHashMap. This
149      * will avoid the need to re-map the mmapping used by PersistentHashMap whenever the underlying
150      * storage grows.
151      */
getUsePreMappingWithFileBackedVector()152     boolean getUsePreMappingWithFileBackedVector();
153 
154     /**
155      * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}.
156      *
157      * <p>Whether or not to use the PersistentHashMap in the QualifiedIdTypeJoinableIndex. If false,
158      * we will use the old IcingDynamicTrie to store key value pairs.
159      */
getUsePersistentHashMap()160     boolean getUsePersistentHashMap();
161 
162     /**
163      * Flag for {@link com.google.android.icing.proto.ResultSpecProto}.
164      *
165      * <p>The maximum byte size to allow in a single page. This limit is only loosely binding.
166      * AppSearch will add results to the page until either 1) AppSearch has retrieved {@link
167      * SearchSpec#getResultCountPerPage()} results or 2) total size of the page exceeds this value.
168      * Therefore, AppSearch will always retrieve at least a single result, even if that result
169      * exceeds this limit.
170      */
getMaxPageBytesLimit()171     int getMaxPageBytesLimit();
172 
173     /**
174      * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}.
175      *
176      * <p>Threshold for integer index bucket split. Integer index stores hits in several buckets,
177      * and splits if # of hits in a single bucket exceed the threshold. Splitting bucket accelerates
178      * numeric search exact query, but potentially downgrades the performance of range query.
179      *
180      * <p>This flag is for rolling out new threshold 65536. If identifying any issues, then change
181      * it back to 341 (the previous bucket split threshold, capacity of full max-sized posting
182      * list).
183      */
getIntegerIndexBucketSplitThreshold()184     int getIntegerIndexBucketSplitThreshold();
185 
186     /**
187      * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}.
188      *
189      * <p>Whether Icing should sort and merge its lite index HitBuffer unsorted tail at indexing
190      * time.
191      *
192      * <p>If set to true, the HitBuffer will be sorted at indexing time after exceeding the sort
193      * threshold. If false, the HifBuffer will be sorted at querying time, before the first query
194      * after inserting new elements into the HitBuffer.
195      */
getLiteIndexSortAtIndexing()196     boolean getLiteIndexSortAtIndexing();
197 
198     /**
199      * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}.
200      *
201      * <p>Size (in bytes) at which Icing's lite index should sort and merge the HitBuffer's unsorted
202      * tail into the sorted head for sorting at indexing time. Size specified here is unsorted tail
203      * section.
204      *
205      * <p>Setting a lower sort size reduces querying latency at the expense of indexing latency.
206      */
getLiteIndexSortSize()207     int getLiteIndexSortSize();
208 
209     /**
210      * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}.
211      *
212      * <p>Whether to use the new qualified Id join index.
213      */
getUseNewQualifiedIdJoinIndex()214     boolean getUseNewQualifiedIdJoinIndex();
215 
216     /**
217      * Flag for {@link com.google.android.icing.proto.IcingSearchEngineOptions}.
218      *
219      * <p>Whether to build the metadata hits used for property existence check, which is required to
220      * support the hasProperty function in advanced query.
221      */
getBuildPropertyExistenceMetadataHits()222     boolean getBuildPropertyExistenceMetadataHits();
223 }
224