aboutsummaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorTim Barron <tjbarron@google.com>2022-12-13 11:49:15 -0800
committerTim Barron <tjbarron@google.com>2022-12-13 13:58:03 -0800
commitffe0a56986f0d400cb63a3d957ac010c3717020f (patch)
tree3e907e6a371a1abb74eee3c61ff04d5d4dcaa828 /java
parent4770cb58f874ad72125aa721954a2d6067b7bc9b (diff)
parent8ddc32ad433ea147de80dcfac2afe58962360f18 (diff)
downloadicing-ffe0a56986f0d400cb63a3d957ac010c3717020f.tar.gz
Merge remote-tracking branch 'aosp/upstream-master' into androidx-main
* aosp/upstream-master: Sync from upstream. Descriptions: ====================================================================== Add ScoringSpec into JoinSpec. Rename joined_document to child_document. ====================================================================== Create JoinedScoredDocumentHit class and refactor ScoredDocumentHitsRanker. ====================================================================== Implement initial Join workflow ====================================================================== Implement the Lexer for Icing Advanced Query Language ====================================================================== Create struct Options for PersistentHashMap ====================================================================== Premapping FileBackedVector ====================================================================== Create class PersistentHashMapKeyMapper ====================================================================== Add integer sections into TokenizedDocument and rename string sections ====================================================================== Create NumericIndex interface and DocHitInfoIteratorNumeric ====================================================================== Implement DummyNumericIndex and unit test ====================================================================== Change PostingListAccessor::Finalize to rvalue member function ====================================================================== Define the Abstract Syntax Tree for Icing's list_filter parser. ====================================================================== Refactor query processing and score ====================================================================== Refactor IcingSearchEngine for AppSearch Dynamite Module 0p APIs ====================================================================== Implement the Lexer for Icing Advanced Scoring Language ====================================================================== Add a common interface for IcingSearchEngine and dynamite client ====================================================================== Implement a subset of the query grammar. ====================================================================== Refactor index processor ====================================================================== Add integer index into IcingSearchEngine and IndexProcessor ====================================================================== Implement the parser for Icing Advanced Scoring Language ====================================================================== Implement IntegerIndexData and PostingListUsedIntegerIndexDataSerializer ====================================================================== Add PostingListAccessor abstract class for common components and methods ====================================================================== Implement PostingListIntegerIndexDataAccessor ====================================================================== Create PostingListIntegerIndexDataAccessorTest ====================================================================== Fix Icing Segmentation tests for word connectors that changed in ICU 72. ====================================================================== Modify the Advanced Query grammar to allow functions to accept expressions. ====================================================================== Implement QueryVisitor. ====================================================================== Enable the Advanced Query Parser to handle member functions ====================================================================== Refactor the Scorer class to support the Advanced Scoring Language ====================================================================== Integrate advanced query parser with the query processor. ====================================================================== Implement support for JoinSpec in Icing. ====================================================================== Implement the Advanced Scoring Language for basic functions and operators ====================================================================== Bug: 208654892 Bug: 249829533 Bug: 256022027 Bug: 261474063 Bug: 240333360 Bug: 193919210 Change-Id: I07d0878666a9e794ab78f8e468dd48750a9bc12a
Diffstat (limited to 'java')
-rw-r--r--java/src/com/google/android/icing/IcingSearchEngine.java607
-rw-r--r--java/src/com/google/android/icing/IcingSearchEngineImpl.java330
-rw-r--r--java/src/com/google/android/icing/IcingSearchEngineInterface.java154
-rw-r--r--java/src/com/google/android/icing/IcingSearchEngineUtils.java471
4 files changed, 1032 insertions, 530 deletions
diff --git a/java/src/com/google/android/icing/IcingSearchEngine.java b/java/src/com/google/android/icing/IcingSearchEngine.java
index 81223f2..47b94a5 100644
--- a/java/src/com/google/android/icing/IcingSearchEngine.java
+++ b/java/src/com/google/android/icing/IcingSearchEngine.java
@@ -14,7 +14,6 @@
package com.google.android.icing;
-import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.icing.proto.DebugInfoResultProto;
@@ -45,17 +44,15 @@ import com.google.android.icing.proto.ScoringSpecProto;
import com.google.android.icing.proto.SearchResultProto;
import com.google.android.icing.proto.SearchSpecProto;
import com.google.android.icing.proto.SetSchemaResultProto;
-import com.google.android.icing.proto.StatusProto;
import com.google.android.icing.proto.StorageInfoResultProto;
import com.google.android.icing.proto.SuggestionResponse;
import com.google.android.icing.proto.SuggestionSpecProto;
import com.google.android.icing.proto.UsageReport;
-import com.google.protobuf.ExtensionRegistryLite;
-import com.google.protobuf.InvalidProtocolBufferException;
-import java.io.Closeable;
/**
- * Java wrapper to access native APIs in external/icing/icing/icing-search-engine.h
+ * Java wrapper to access {@link IcingSearchEngineImpl}.
+ *
+ * <p>It converts byte array from {@link IcingSearchEngineImpl} to corresponding protos.
*
* <p>If this instance has been closed, the instance is no longer usable.
*
@@ -63,574 +60,197 @@ import java.io.Closeable;
*
* <p>NOTE: This class is NOT thread-safe.
*/
-public class IcingSearchEngine implements Closeable {
+public class IcingSearchEngine implements IcingSearchEngineInterface {
private static final String TAG = "IcingSearchEngine";
- private static final ExtensionRegistryLite EXTENSION_REGISTRY_LITE =
- ExtensionRegistryLite.getEmptyRegistry();
-
- private long nativePointer;
-
- private boolean closed = false;
-
- static {
- // NOTE: This can fail with an UnsatisfiedLinkError
- System.loadLibrary("icing");
- }
+ private final IcingSearchEngineImpl icingSearchEngineImpl;
/**
* @throws IllegalStateException if IcingSearchEngine fails to be created
*/
public IcingSearchEngine(@NonNull IcingSearchEngineOptions options) {
- nativePointer = nativeCreate(options.toByteArray());
- if (nativePointer == 0) {
- Log.e(TAG, "Failed to create IcingSearchEngine.");
- throw new IllegalStateException("Failed to create IcingSearchEngine.");
- }
- }
-
- private void throwIfClosed() {
- if (closed) {
- throw new IllegalStateException("Trying to use a closed IcingSearchEngine instance.");
- }
+ icingSearchEngineImpl = new IcingSearchEngineImpl(options.toByteArray());
}
@Override
public void close() {
- if (closed) {
- return;
- }
-
- if (nativePointer != 0) {
- nativeDestroy(this);
- }
- nativePointer = 0;
- closed = true;
+ icingSearchEngineImpl.close();
}
@Override
protected void finalize() throws Throwable {
- close();
+ icingSearchEngineImpl.close();
super.finalize();
}
@NonNull
+ @Override
public InitializeResultProto initialize() {
- throwIfClosed();
-
- byte[] initializeResultBytes = nativeInitialize(this);
- if (initializeResultBytes == null) {
- Log.e(TAG, "Received null InitializeResult from native.");
- return InitializeResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return InitializeResultProto.parseFrom(initializeResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing InitializeResultProto.", e);
- return InitializeResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToInitializeResultProto(
+ icingSearchEngineImpl.initialize());
}
@NonNull
+ @Override
public SetSchemaResultProto setSchema(@NonNull SchemaProto schema) {
return setSchema(schema, /*ignoreErrorsAndDeleteDocuments=*/ false);
}
@NonNull
+ @Override
public SetSchemaResultProto setSchema(
@NonNull SchemaProto schema, boolean ignoreErrorsAndDeleteDocuments) {
- throwIfClosed();
-
- byte[] setSchemaResultBytes =
- nativeSetSchema(this, schema.toByteArray(), ignoreErrorsAndDeleteDocuments);
- if (setSchemaResultBytes == null) {
- Log.e(TAG, "Received null SetSchemaResultProto from native.");
- return SetSchemaResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return SetSchemaResultProto.parseFrom(setSchemaResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing SetSchemaResultProto.", e);
- return SetSchemaResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToSetSchemaResultProto(
+ icingSearchEngineImpl.setSchema(schema.toByteArray(), ignoreErrorsAndDeleteDocuments));
}
@NonNull
+ @Override
public GetSchemaResultProto getSchema() {
- throwIfClosed();
-
- byte[] getSchemaResultBytes = nativeGetSchema(this);
- if (getSchemaResultBytes == null) {
- Log.e(TAG, "Received null GetSchemaResultProto from native.");
- return GetSchemaResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return GetSchemaResultProto.parseFrom(getSchemaResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing GetSchemaResultProto.", e);
- return GetSchemaResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToGetSchemaResultProto(
+ icingSearchEngineImpl.getSchema());
}
@NonNull
+ @Override
public GetSchemaTypeResultProto getSchemaType(@NonNull String schemaType) {
- throwIfClosed();
-
- byte[] getSchemaTypeResultBytes = nativeGetSchemaType(this, schemaType);
- if (getSchemaTypeResultBytes == null) {
- Log.e(TAG, "Received null GetSchemaTypeResultProto from native.");
- return GetSchemaTypeResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return GetSchemaTypeResultProto.parseFrom(getSchemaTypeResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing GetSchemaTypeResultProto.", e);
- return GetSchemaTypeResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToGetSchemaTypeResultProto(
+ icingSearchEngineImpl.getSchemaType(schemaType));
}
@NonNull
+ @Override
public PutResultProto put(@NonNull DocumentProto document) {
- throwIfClosed();
-
- byte[] putResultBytes = nativePut(this, document.toByteArray());
- if (putResultBytes == null) {
- Log.e(TAG, "Received null PutResultProto from native.");
- return PutResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return PutResultProto.parseFrom(putResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing PutResultProto.", e);
- return PutResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToPutResultProto(
+ icingSearchEngineImpl.put(document.toByteArray()));
}
@NonNull
+ @Override
public GetResultProto get(
@NonNull String namespace, @NonNull String uri, @NonNull GetResultSpecProto getResultSpec) {
- throwIfClosed();
-
- byte[] getResultBytes = nativeGet(this, namespace, uri, getResultSpec.toByteArray());
- if (getResultBytes == null) {
- Log.e(TAG, "Received null GetResultProto from native.");
- return GetResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return GetResultProto.parseFrom(getResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing GetResultProto.", e);
- return GetResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToGetResultProto(
+ icingSearchEngineImpl.get(namespace, uri, getResultSpec.toByteArray()));
}
@NonNull
+ @Override
public ReportUsageResultProto reportUsage(@NonNull UsageReport usageReport) {
- throwIfClosed();
-
- byte[] reportUsageResultBytes = nativeReportUsage(this, usageReport.toByteArray());
- if (reportUsageResultBytes == null) {
- Log.e(TAG, "Received null ReportUsageResultProto from native.");
- return ReportUsageResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return ReportUsageResultProto.parseFrom(reportUsageResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing ReportUsageResultProto.", e);
- return ReportUsageResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToReportUsageResultProto(
+ icingSearchEngineImpl.reportUsage(usageReport.toByteArray()));
}
@NonNull
+ @Override
public GetAllNamespacesResultProto getAllNamespaces() {
- throwIfClosed();
-
- byte[] getAllNamespacesResultBytes = nativeGetAllNamespaces(this);
- if (getAllNamespacesResultBytes == null) {
- Log.e(TAG, "Received null GetAllNamespacesResultProto from native.");
- return GetAllNamespacesResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return GetAllNamespacesResultProto.parseFrom(
- getAllNamespacesResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing GetAllNamespacesResultProto.", e);
- return GetAllNamespacesResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToGetAllNamespacesResultProto(
+ icingSearchEngineImpl.getAllNamespaces());
}
@NonNull
+ @Override
public SearchResultProto search(
@NonNull SearchSpecProto searchSpec,
@NonNull ScoringSpecProto scoringSpec,
@NonNull ResultSpecProto resultSpec) {
- throwIfClosed();
-
- // Note that on Android System.currentTimeMillis() is the standard "wall" clock and can be set
- // by the user or the phone network so the time may jump backwards or forwards unpredictably.
- // This could lead to inaccurate final JNI latency calculations or unexpected negative numbers
- // in the case where the phone time is changed while sending data across JNI layers.
- // However these occurrences should be very rare, so we will keep usage of
- // System.currentTimeMillis() due to the lack of better time functions that can provide a
- // consistent timestamp across all platforms.
- long javaToNativeStartTimestampMs = System.currentTimeMillis();
- byte[] searchResultBytes =
- nativeSearch(
- this,
- searchSpec.toByteArray(),
- scoringSpec.toByteArray(),
- resultSpec.toByteArray(),
- javaToNativeStartTimestampMs);
- if (searchResultBytes == null) {
- Log.e(TAG, "Received null SearchResultProto from native.");
- return SearchResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- SearchResultProto.Builder searchResultProtoBuilder =
- SearchResultProto.newBuilder().mergeFrom(searchResultBytes, EXTENSION_REGISTRY_LITE);
- setNativeToJavaJniLatency(searchResultProtoBuilder);
- return searchResultProtoBuilder.build();
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing SearchResultProto.", e);
- return SearchResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToSearchResultProto(
+ icingSearchEngineImpl.search(
+ searchSpec.toByteArray(), scoringSpec.toByteArray(), resultSpec.toByteArray()));
}
@NonNull
+ @Override
public SearchResultProto getNextPage(long nextPageToken) {
- throwIfClosed();
-
- byte[] searchResultBytes = nativeGetNextPage(this, nextPageToken, System.currentTimeMillis());
- if (searchResultBytes == null) {
- Log.e(TAG, "Received null SearchResultProto from native.");
- return SearchResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- SearchResultProto.Builder searchResultProtoBuilder =
- SearchResultProto.newBuilder().mergeFrom(searchResultBytes, EXTENSION_REGISTRY_LITE);
- setNativeToJavaJniLatency(searchResultProtoBuilder);
- return searchResultProtoBuilder.build();
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing SearchResultProto.", e);
- return SearchResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
- }
-
- private void setNativeToJavaJniLatency(SearchResultProto.Builder searchResultProtoBuilder) {
- int nativeToJavaLatencyMs =
- (int)
- (System.currentTimeMillis()
- - searchResultProtoBuilder.getQueryStats().getNativeToJavaStartTimestampMs());
- searchResultProtoBuilder.setQueryStats(
- searchResultProtoBuilder.getQueryStats().toBuilder()
- .setNativeToJavaJniLatencyMs(nativeToJavaLatencyMs));
+ return IcingSearchEngineUtils.byteArrayToSearchResultProto(
+ icingSearchEngineImpl.getNextPage(nextPageToken));
}
@NonNull
+ @Override
public void invalidateNextPageToken(long nextPageToken) {
- throwIfClosed();
-
- nativeInvalidateNextPageToken(this, nextPageToken);
+ icingSearchEngineImpl.invalidateNextPageToken(nextPageToken);
}
@NonNull
+ @Override
public DeleteResultProto delete(@NonNull String namespace, @NonNull String uri) {
- throwIfClosed();
-
- byte[] deleteResultBytes = nativeDelete(this, namespace, uri);
- if (deleteResultBytes == null) {
- Log.e(TAG, "Received null DeleteResultProto from native.");
- return DeleteResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return DeleteResultProto.parseFrom(deleteResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing DeleteResultProto.", e);
- return DeleteResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToDeleteResultProto(
+ icingSearchEngineImpl.delete(namespace, uri));
}
@NonNull
+ @Override
public SuggestionResponse searchSuggestions(@NonNull SuggestionSpecProto suggestionSpec) {
- byte[] suggestionResponseBytes = nativeSearchSuggestions(this, suggestionSpec.toByteArray());
- if (suggestionResponseBytes == null) {
- Log.e(TAG, "Received null suggestionResponseBytes from native.");
- return SuggestionResponse.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return SuggestionResponse.parseFrom(suggestionResponseBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing suggestionResponseBytes.", e);
- return SuggestionResponse.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToSuggestionResponse(
+ icingSearchEngineImpl.searchSuggestions(suggestionSpec.toByteArray()));
}
@NonNull
+ @Override
public DeleteByNamespaceResultProto deleteByNamespace(@NonNull String namespace) {
- throwIfClosed();
-
- byte[] deleteByNamespaceResultBytes = nativeDeleteByNamespace(this, namespace);
- if (deleteByNamespaceResultBytes == null) {
- Log.e(TAG, "Received null DeleteByNamespaceResultProto from native.");
- return DeleteByNamespaceResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return DeleteByNamespaceResultProto.parseFrom(
- deleteByNamespaceResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing DeleteByNamespaceResultProto.", e);
- return DeleteByNamespaceResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToDeleteByNamespaceResultProto(
+ icingSearchEngineImpl.deleteByNamespace(namespace));
}
@NonNull
+ @Override
public DeleteBySchemaTypeResultProto deleteBySchemaType(@NonNull String schemaType) {
- throwIfClosed();
-
- byte[] deleteBySchemaTypeResultBytes = nativeDeleteBySchemaType(this, schemaType);
- if (deleteBySchemaTypeResultBytes == null) {
- Log.e(TAG, "Received null DeleteBySchemaTypeResultProto from native.");
- return DeleteBySchemaTypeResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return DeleteBySchemaTypeResultProto.parseFrom(
- deleteBySchemaTypeResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing DeleteBySchemaTypeResultProto.", e);
- return DeleteBySchemaTypeResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToDeleteBySchemaTypeResultProto(
+ icingSearchEngineImpl.deleteBySchemaType(schemaType));
}
@NonNull
+ @Override
public DeleteByQueryResultProto deleteByQuery(@NonNull SearchSpecProto searchSpec) {
return deleteByQuery(searchSpec, /*returnDeletedDocumentInfo=*/ false);
}
@NonNull
+ @Override
public DeleteByQueryResultProto deleteByQuery(
@NonNull SearchSpecProto searchSpec, boolean returnDeletedDocumentInfo) {
- throwIfClosed();
-
- byte[] deleteResultBytes =
- nativeDeleteByQuery(this, searchSpec.toByteArray(), returnDeletedDocumentInfo);
- if (deleteResultBytes == null) {
- Log.e(TAG, "Received null DeleteResultProto from native.");
- return DeleteByQueryResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return DeleteByQueryResultProto.parseFrom(deleteResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing DeleteResultProto.", e);
- return DeleteByQueryResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToDeleteByQueryResultProto(
+ icingSearchEngineImpl.deleteByQuery(searchSpec.toByteArray(), returnDeletedDocumentInfo));
}
@NonNull
+ @Override
public PersistToDiskResultProto persistToDisk(@NonNull PersistType.Code persistTypeCode) {
- throwIfClosed();
-
- byte[] persistToDiskResultBytes = nativePersistToDisk(this, persistTypeCode.getNumber());
- if (persistToDiskResultBytes == null) {
- Log.e(TAG, "Received null PersistToDiskResultProto from native.");
- return PersistToDiskResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return PersistToDiskResultProto.parseFrom(persistToDiskResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing PersistToDiskResultProto.", e);
- return PersistToDiskResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToPersistToDiskResultProto(
+ icingSearchEngineImpl.persistToDisk(persistTypeCode.getNumber()));
}
@NonNull
+ @Override
public OptimizeResultProto optimize() {
- throwIfClosed();
-
- byte[] optimizeResultBytes = nativeOptimize(this);
- if (optimizeResultBytes == null) {
- Log.e(TAG, "Received null OptimizeResultProto from native.");
- return OptimizeResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return OptimizeResultProto.parseFrom(optimizeResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing OptimizeResultProto.", e);
- return OptimizeResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToOptimizeResultProto(icingSearchEngineImpl.optimize());
}
@NonNull
+ @Override
public GetOptimizeInfoResultProto getOptimizeInfo() {
- throwIfClosed();
-
- byte[] getOptimizeInfoResultBytes = nativeGetOptimizeInfo(this);
- if (getOptimizeInfoResultBytes == null) {
- Log.e(TAG, "Received null GetOptimizeInfoResultProto from native.");
- return GetOptimizeInfoResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return GetOptimizeInfoResultProto.parseFrom(
- getOptimizeInfoResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing GetOptimizeInfoResultProto.", e);
- return GetOptimizeInfoResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToGetOptimizeInfoResultProto(
+ icingSearchEngineImpl.getOptimizeInfo());
}
@NonNull
+ @Override
public StorageInfoResultProto getStorageInfo() {
- throwIfClosed();
-
- byte[] storageInfoResultProtoBytes = nativeGetStorageInfo(this);
- if (storageInfoResultProtoBytes == null) {
- Log.e(TAG, "Received null StorageInfoResultProto from native.");
- return StorageInfoResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return StorageInfoResultProto.parseFrom(storageInfoResultProtoBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing GetOptimizeInfoResultProto.", e);
- return StorageInfoResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToStorageInfoResultProto(
+ icingSearchEngineImpl.getStorageInfo());
}
@NonNull
+ @Override
public DebugInfoResultProto getDebugInfo(DebugInfoVerbosity.Code verbosity) {
- throwIfClosed();
-
- byte[] debugInfoResultProtoBytes = nativeGetDebugInfo(this, verbosity.getNumber());
- if (debugInfoResultProtoBytes == null) {
- Log.e(TAG, "Received null DebugInfoResultProto from native.");
- return DebugInfoResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return DebugInfoResultProto.parseFrom(debugInfoResultProtoBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing DebugInfoResultProto.", e);
- return DebugInfoResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToDebugInfoResultProto(
+ icingSearchEngineImpl.getDebugInfo(verbosity.getNumber()));
}
@NonNull
+ @Override
public ResetResultProto reset() {
- throwIfClosed();
-
- byte[] resetResultBytes = nativeReset(this);
- if (resetResultBytes == null) {
- Log.e(TAG, "Received null ResetResultProto from native.");
- return ResetResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
-
- try {
- return ResetResultProto.parseFrom(resetResultBytes, EXTENSION_REGISTRY_LITE);
- } catch (InvalidProtocolBufferException e) {
- Log.e(TAG, "Error parsing ResetResultProto.", e);
- return ResetResultProto.newBuilder()
- .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
- .build();
- }
+ return IcingSearchEngineUtils.byteArrayToResetResultProto(icingSearchEngineImpl.reset());
}
public static boolean shouldLog(LogSeverity.Code severity) {
@@ -638,7 +258,7 @@ public class IcingSearchEngine implements Closeable {
}
public static boolean shouldLog(LogSeverity.Code severity, short verbosity) {
- return nativeShouldLog((short) severity.getNumber(), verbosity);
+ return IcingSearchEngineImpl.shouldLog((short) severity.getNumber(), verbosity);
}
public static boolean setLoggingLevel(LogSeverity.Code severity) {
@@ -646,84 +266,11 @@ public class IcingSearchEngine implements Closeable {
}
public static boolean setLoggingLevel(LogSeverity.Code severity, short verbosity) {
- return nativeSetLoggingLevel((short) severity.getNumber(), verbosity);
+ return IcingSearchEngineImpl.setLoggingLevel((short) severity.getNumber(), verbosity);
}
@Nullable
public static String getLoggingTag() {
- String tag = nativeGetLoggingTag();
- if (tag == null) {
- Log.e(TAG, "Received null logging tag from native.");
- }
- return tag;
+ return IcingSearchEngineImpl.getLoggingTag();
}
-
- private static native long nativeCreate(byte[] icingSearchEngineOptionsBytes);
-
- private static native void nativeDestroy(IcingSearchEngine instance);
-
- private static native byte[] nativeInitialize(IcingSearchEngine instance);
-
- private static native byte[] nativeSetSchema(
- IcingSearchEngine instance, byte[] schemaBytes, boolean ignoreErrorsAndDeleteDocuments);
-
- private static native byte[] nativeGetSchema(IcingSearchEngine instance);
-
- private static native byte[] nativeGetSchemaType(IcingSearchEngine instance, String schemaType);
-
- private static native byte[] nativePut(IcingSearchEngine instance, byte[] documentBytes);
-
- private static native byte[] nativeGet(
- IcingSearchEngine instance, String namespace, String uri, byte[] getResultSpecBytes);
-
- private static native byte[] nativeReportUsage(
- IcingSearchEngine instance, byte[] usageReportBytes);
-
- private static native byte[] nativeGetAllNamespaces(IcingSearchEngine instance);
-
- private static native byte[] nativeSearch(
- IcingSearchEngine instance,
- byte[] searchSpecBytes,
- byte[] scoringSpecBytes,
- byte[] resultSpecBytes,
- long javaToNativeStartTimestampMs);
-
- private static native byte[] nativeGetNextPage(
- IcingSearchEngine instance, long nextPageToken, long javaToNativeStartTimestampMs);
-
- private static native void nativeInvalidateNextPageToken(
- IcingSearchEngine instance, long nextPageToken);
-
- private static native byte[] nativeDelete(
- IcingSearchEngine instance, String namespace, String uri);
-
- private static native byte[] nativeDeleteByNamespace(
- IcingSearchEngine instance, String namespace);
-
- private static native byte[] nativeDeleteBySchemaType(
- IcingSearchEngine instance, String schemaType);
-
- private static native byte[] nativeDeleteByQuery(
- IcingSearchEngine instance, byte[] searchSpecBytes, boolean returnDeletedDocumentInfo);
-
- private static native byte[] nativePersistToDisk(IcingSearchEngine instance, int persistType);
-
- private static native byte[] nativeOptimize(IcingSearchEngine instance);
-
- private static native byte[] nativeGetOptimizeInfo(IcingSearchEngine instance);
-
- private static native byte[] nativeGetStorageInfo(IcingSearchEngine instance);
-
- private static native byte[] nativeReset(IcingSearchEngine instance);
-
- private static native byte[] nativeSearchSuggestions(
- IcingSearchEngine instance, byte[] suggestionSpecBytes);
-
- private static native byte[] nativeGetDebugInfo(IcingSearchEngine instance, int verbosity);
-
- private static native boolean nativeShouldLog(short severity, short verbosity);
-
- private static native boolean nativeSetLoggingLevel(short severity, short verbosity);
-
- private static native String nativeGetLoggingTag();
}
diff --git a/java/src/com/google/android/icing/IcingSearchEngineImpl.java b/java/src/com/google/android/icing/IcingSearchEngineImpl.java
new file mode 100644
index 0000000..8e79a88
--- /dev/null
+++ b/java/src/com/google/android/icing/IcingSearchEngineImpl.java
@@ -0,0 +1,330 @@
+// Copyright (C) 2019 Google LLC
+//
+// 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.google.android.icing;
+
+import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import java.io.Closeable;
+
+/**
+ * Java wrapper to access native APIs in external/icing/icing/icing-search-engine.h
+ *
+ * <p>If this instance has been closed, the instance is no longer usable.
+ *
+ * <p>Keep this class to be non-Final so that it can be mocked in AppSearch.
+ *
+ * <p>NOTE: This class is NOT thread-safe.
+ */
+public class IcingSearchEngineImpl implements Closeable {
+
+ private static final String TAG = "IcingSearchEngineImpl";
+
+ private long nativePointer;
+
+ private boolean closed = false;
+
+ static {
+ // NOTE: This can fail with an UnsatisfiedLinkError
+ System.loadLibrary("icing");
+ }
+
+ /**
+ * @throws IllegalStateException if IcingSearchEngineImpl fails to be created
+ */
+ public IcingSearchEngineImpl(@NonNull byte[] optionsBytes) {
+ nativePointer = nativeCreate(optionsBytes);
+ if (nativePointer == 0) {
+ Log.e(TAG, "Failed to create IcingSearchEngineImpl.");
+ throw new IllegalStateException("Failed to create IcingSearchEngineImpl.");
+ }
+ }
+
+ private void throwIfClosed() {
+ if (closed) {
+ throw new IllegalStateException("Trying to use a closed IcingSearchEngineImpl instance.");
+ }
+ }
+
+ @Override
+ public void close() {
+ if (closed) {
+ return;
+ }
+
+ if (nativePointer != 0) {
+ nativeDestroy(this);
+ }
+ nativePointer = 0;
+ closed = true;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ close();
+ super.finalize();
+ }
+
+ @Nullable
+ public byte[] initialize() {
+ throwIfClosed();
+ return nativeInitialize(this);
+ }
+
+ @Nullable
+ public byte[] setSchema(@NonNull byte[] schemaBytes) {
+ return setSchema(schemaBytes, /* ignoreErrorsAndDeleteDocuments= */ false);
+ }
+
+ @Nullable
+ public byte[] setSchema(@NonNull byte[] schemaBytes, boolean ignoreErrorsAndDeleteDocuments) {
+ throwIfClosed();
+ return nativeSetSchema(this, schemaBytes, ignoreErrorsAndDeleteDocuments);
+ }
+
+ @Nullable
+ public byte[] getSchema() {
+ throwIfClosed();
+ return nativeGetSchema(this);
+ }
+
+ @Nullable
+ public byte[] getSchemaType(@NonNull String schemaType) {
+ throwIfClosed();
+ return nativeGetSchemaType(this, schemaType);
+ }
+
+ @Nullable
+ public byte[] put(@NonNull byte[] documentBytes) {
+ throwIfClosed();
+ return nativePut(this, documentBytes);
+ }
+
+ @Nullable
+ public byte[] get(
+ @NonNull String namespace, @NonNull String uri, @NonNull byte[] getResultSpecBytes) {
+ throwIfClosed();
+ return nativeGet(this, namespace, uri, getResultSpecBytes);
+ }
+
+ @Nullable
+ public byte[] reportUsage(@NonNull byte[] usageReportBytes) {
+ throwIfClosed();
+ return nativeReportUsage(this, usageReportBytes);
+ }
+
+ @Nullable
+ public byte[] getAllNamespaces() {
+ throwIfClosed();
+ return nativeGetAllNamespaces(this);
+ }
+
+ @Nullable
+ public byte[] search(
+ @NonNull byte[] searchSpecBytes,
+ @NonNull byte[] scoringSpecBytes,
+ @NonNull byte[] resultSpecBytes) {
+ throwIfClosed();
+
+ // Note that on Android System.currentTimeMillis() is the standard "wall" clock and can be set
+ // by the user or the phone network so the time may jump backwards or forwards unpredictably.
+ // This could lead to inaccurate final JNI latency calculations or unexpected negative numbers
+ // in the case where the phone time is changed while sending data across JNI layers.
+ // However these occurrences should be very rare, so we will keep usage of
+ // System.currentTimeMillis() due to the lack of better time functions that can provide a
+ // consistent timestamp across all platforms.
+ long javaToNativeStartTimestampMs = System.currentTimeMillis();
+ return nativeSearch(
+ this, searchSpecBytes, scoringSpecBytes, resultSpecBytes, javaToNativeStartTimestampMs);
+ }
+
+ @Nullable
+ public byte[] getNextPage(long nextPageToken) {
+ throwIfClosed();
+ return nativeGetNextPage(this, nextPageToken, System.currentTimeMillis());
+ }
+
+ @NonNull
+ public void invalidateNextPageToken(long nextPageToken) {
+ throwIfClosed();
+ nativeInvalidateNextPageToken(this, nextPageToken);
+ }
+
+ @Nullable
+ public byte[] delete(@NonNull String namespace, @NonNull String uri) {
+ throwIfClosed();
+ return nativeDelete(this, namespace, uri);
+ }
+
+ @Nullable
+ public byte[] searchSuggestions(@NonNull byte[] suggestionSpecBytes) {
+ throwIfClosed();
+ return nativeSearchSuggestions(this, suggestionSpecBytes);
+ }
+
+ @Nullable
+ public byte[] deleteByNamespace(@NonNull String namespace) {
+ throwIfClosed();
+ return nativeDeleteByNamespace(this, namespace);
+ }
+
+ @Nullable
+ public byte[] deleteBySchemaType(@NonNull String schemaType) {
+ throwIfClosed();
+ return nativeDeleteBySchemaType(this, schemaType);
+ }
+
+ @Nullable
+ public byte[] deleteByQuery(@NonNull byte[] searchSpecBytes) {
+ return deleteByQuery(searchSpecBytes, /* returnDeletedDocumentInfo= */ false);
+ }
+
+ @Nullable
+ public byte[] deleteByQuery(@NonNull byte[] searchSpecBytes, boolean returnDeletedDocumentInfo) {
+ throwIfClosed();
+ return nativeDeleteByQuery(this, searchSpecBytes, returnDeletedDocumentInfo);
+ }
+
+ @Nullable
+ public byte[] persistToDisk(int persistTypeCode) {
+ throwIfClosed();
+ return nativePersistToDisk(this, persistTypeCode);
+ }
+
+ @Nullable
+ public byte[] optimize() {
+ throwIfClosed();
+ return nativeOptimize(this);
+ }
+
+ @Nullable
+ public byte[] getOptimizeInfo() {
+ throwIfClosed();
+ return nativeGetOptimizeInfo(this);
+ }
+
+ @Nullable
+ public byte[] getStorageInfo() {
+ throwIfClosed();
+ return nativeGetStorageInfo(this);
+ }
+
+ @Nullable
+ public byte[] getDebugInfo(int verbosityCode) {
+ throwIfClosed();
+ return nativeGetDebugInfo(this, verbosityCode);
+ }
+
+ @Nullable
+ public byte[] reset() {
+ throwIfClosed();
+ return nativeReset(this);
+ }
+
+ public static boolean shouldLog(short severity) {
+ return shouldLog(severity, (short) 0);
+ }
+
+ public static boolean shouldLog(short severity, short verbosity) {
+ return nativeShouldLog(severity, verbosity);
+ }
+
+ public static boolean setLoggingLevel(short severity) {
+ return setLoggingLevel(severity, (short) 0);
+ }
+
+ public static boolean setLoggingLevel(short severity, short verbosity) {
+ return nativeSetLoggingLevel(severity, verbosity);
+ }
+
+ @Nullable
+ public static String getLoggingTag() {
+ String tag = nativeGetLoggingTag();
+ if (tag == null) {
+ Log.e(TAG, "Received null logging tag from native.");
+ }
+ return tag;
+ }
+
+ private static native long nativeCreate(byte[] icingSearchEngineOptionsBytes);
+
+ private static native void nativeDestroy(IcingSearchEngineImpl instance);
+
+ private static native byte[] nativeInitialize(IcingSearchEngineImpl instance);
+
+ private static native byte[] nativeSetSchema(
+ IcingSearchEngineImpl instance, byte[] schemaBytes, boolean ignoreErrorsAndDeleteDocuments);
+
+ private static native byte[] nativeGetSchema(IcingSearchEngineImpl instance);
+
+ private static native byte[] nativeGetSchemaType(
+ IcingSearchEngineImpl instance, String schemaType);
+
+ private static native byte[] nativePut(IcingSearchEngineImpl instance, byte[] documentBytes);
+
+ private static native byte[] nativeGet(
+ IcingSearchEngineImpl instance, String namespace, String uri, byte[] getResultSpecBytes);
+
+ private static native byte[] nativeReportUsage(
+ IcingSearchEngineImpl instance, byte[] usageReportBytes);
+
+ private static native byte[] nativeGetAllNamespaces(IcingSearchEngineImpl instance);
+
+ private static native byte[] nativeSearch(
+ IcingSearchEngineImpl instance,
+ byte[] searchSpecBytes,
+ byte[] scoringSpecBytes,
+ byte[] resultSpecBytes,
+ long javaToNativeStartTimestampMs);
+
+ private static native byte[] nativeGetNextPage(
+ IcingSearchEngineImpl instance, long nextPageToken, long javaToNativeStartTimestampMs);
+
+ private static native void nativeInvalidateNextPageToken(
+ IcingSearchEngineImpl instance, long nextPageToken);
+
+ private static native byte[] nativeDelete(
+ IcingSearchEngineImpl instance, String namespace, String uri);
+
+ private static native byte[] nativeDeleteByNamespace(
+ IcingSearchEngineImpl instance, String namespace);
+
+ private static native byte[] nativeDeleteBySchemaType(
+ IcingSearchEngineImpl instance, String schemaType);
+
+ private static native byte[] nativeDeleteByQuery(
+ IcingSearchEngineImpl instance, byte[] searchSpecBytes, boolean returnDeletedDocumentInfo);
+
+ private static native byte[] nativePersistToDisk(IcingSearchEngineImpl instance, int persistType);
+
+ private static native byte[] nativeOptimize(IcingSearchEngineImpl instance);
+
+ private static native byte[] nativeGetOptimizeInfo(IcingSearchEngineImpl instance);
+
+ private static native byte[] nativeGetStorageInfo(IcingSearchEngineImpl instance);
+
+ private static native byte[] nativeReset(IcingSearchEngineImpl instance);
+
+ private static native byte[] nativeSearchSuggestions(
+ IcingSearchEngineImpl instance, byte[] suggestionSpecBytes);
+
+ private static native byte[] nativeGetDebugInfo(IcingSearchEngineImpl instance, int verbosity);
+
+ private static native boolean nativeShouldLog(short severity, short verbosity);
+
+ private static native boolean nativeSetLoggingLevel(short severity, short verbosity);
+
+ private static native String nativeGetLoggingTag();
+}
diff --git a/java/src/com/google/android/icing/IcingSearchEngineInterface.java b/java/src/com/google/android/icing/IcingSearchEngineInterface.java
new file mode 100644
index 0000000..5922716
--- /dev/null
+++ b/java/src/com/google/android/icing/IcingSearchEngineInterface.java
@@ -0,0 +1,154 @@
+package com.google.android.icing;
+
+import android.os.RemoteException;
+import com.google.android.icing.proto.DebugInfoResultProto;
+import com.google.android.icing.proto.DebugInfoVerbosity;
+import com.google.android.icing.proto.DeleteByNamespaceResultProto;
+import com.google.android.icing.proto.DeleteByQueryResultProto;
+import com.google.android.icing.proto.DeleteBySchemaTypeResultProto;
+import com.google.android.icing.proto.DeleteResultProto;
+import com.google.android.icing.proto.DocumentProto;
+import com.google.android.icing.proto.GetAllNamespacesResultProto;
+import com.google.android.icing.proto.GetOptimizeInfoResultProto;
+import com.google.android.icing.proto.GetResultProto;
+import com.google.android.icing.proto.GetResultSpecProto;
+import com.google.android.icing.proto.GetSchemaResultProto;
+import com.google.android.icing.proto.GetSchemaTypeResultProto;
+import com.google.android.icing.proto.InitializeResultProto;
+import com.google.android.icing.proto.OptimizeResultProto;
+import com.google.android.icing.proto.PersistToDiskResultProto;
+import com.google.android.icing.proto.PersistType;
+import com.google.android.icing.proto.PutResultProto;
+import com.google.android.icing.proto.ReportUsageResultProto;
+import com.google.android.icing.proto.ResetResultProto;
+import com.google.android.icing.proto.ResultSpecProto;
+import com.google.android.icing.proto.SchemaProto;
+import com.google.android.icing.proto.ScoringSpecProto;
+import com.google.android.icing.proto.SearchResultProto;
+import com.google.android.icing.proto.SearchSpecProto;
+import com.google.android.icing.proto.SetSchemaResultProto;
+import com.google.android.icing.proto.StorageInfoResultProto;
+import com.google.android.icing.proto.SuggestionResponse;
+import com.google.android.icing.proto.SuggestionSpecProto;
+import com.google.android.icing.proto.UsageReport;
+import java.io.Closeable;
+
+/**
+ * A common user-facing interface to expose the funcationalities provided by Icing Library.
+ *
+ * <p>All the methods here throw {@link RemoteException} because the implementation for
+ * gmscore-appsearch-dynamite will throw it.
+ */
+public interface IcingSearchEngineInterface extends Closeable {
+ /**
+ * Initializes the current IcingSearchEngine implementation.
+ *
+ * <p>Internally the icing instance will be initialized.
+ */
+ InitializeResultProto initialize();
+
+ /** Sets the schema for the icing instance. */
+ SetSchemaResultProto setSchema(SchemaProto schema);
+
+ /**
+ * Sets the schema for the icing instance.
+ *
+ * @param ignoreErrorsAndDeleteDocuments force to set the schema and delete documents in case of
+ * incompatible schema change.
+ */
+ SetSchemaResultProto setSchema(SchemaProto schema, boolean ignoreErrorsAndDeleteDocuments);
+
+ /** Gets the schema for the icing instance. */
+ GetSchemaResultProto getSchema();
+
+ /**
+ * Gets the schema for the icing instance.
+ *
+ * @param schemaType type of the schema.
+ */
+ GetSchemaTypeResultProto getSchemaType(String schemaType);
+
+ /** Puts the document. */
+ PutResultProto put(DocumentProto document);
+
+ /**
+ * Gets the document.
+ *
+ * @param namespace namespace of the document.
+ * @param uri uri of the document.
+ * @param getResultSpec the spec for getting the document.
+ */
+ GetResultProto get(String namespace, String uri, GetResultSpecProto getResultSpec);
+
+ /** Reports usage. */
+ ReportUsageResultProto reportUsage(UsageReport usageReport);
+
+ /** Gets all namespaces. */
+ GetAllNamespacesResultProto getAllNamespaces();
+
+ /**
+ * Searches over the documents.
+ *
+ * <p>Documents need to be retrieved on the following {@link #getNextPage} calls on the returned
+ * {@link SearchResultProto}.
+ */
+ SearchResultProto search(
+ SearchSpecProto searchSpec, ScoringSpecProto scoringSpec, ResultSpecProto resultSpec);
+
+ /** Gets the next page. */
+ SearchResultProto getNextPage(long nextPageToken);
+
+ /** Invalidates the next page token. */
+ void invalidateNextPageToken(long nextPageToken);
+
+ /**
+ * Deletes the document.
+ *
+ * @param namespace the namespace the document to be deleted belong to.
+ * @param uri the uri for the document to be deleted.
+ */
+ DeleteResultProto delete(String namespace, String uri);
+
+ /** Returns the suggestions for the search query. */
+ SuggestionResponse searchSuggestions(SuggestionSpecProto suggestionSpec);
+
+ /** Deletes documents by the namespace. */
+ DeleteByNamespaceResultProto deleteByNamespace(String namespace);
+
+ /** Deletes documents by the schema type. */
+ DeleteBySchemaTypeResultProto deleteBySchemaType(String schemaType);
+
+ /** Deletes documents by the search query. */
+ DeleteByQueryResultProto deleteByQuery(SearchSpecProto searchSpec);
+
+ /**
+ * Deletes document by the search query
+ *
+ * @param returnDeletedDocumentInfo whether additional information about deleted documents will be
+ * included in {@link DeleteByQueryResultProto}.
+ */
+ DeleteByQueryResultProto deleteByQuery(
+ SearchSpecProto searchSpec, boolean returnDeletedDocumentInfo);
+
+ /** Makes sure every update/delete received till this point is flushed to disk. */
+ PersistToDiskResultProto persistToDisk(PersistType.Code persistTypeCode);
+
+ /** Makes the icing instance run tasks that are too expensive to be run in real-time. */
+ OptimizeResultProto optimize();
+
+ /** Gets information about the optimization. */
+ GetOptimizeInfoResultProto getOptimizeInfo();
+
+ /** Gets information about the storage. */
+ StorageInfoResultProto getStorageInfo();
+
+ /** Gets the debug information for the current icing instance. */
+ DebugInfoResultProto getDebugInfo(DebugInfoVerbosity.Code verbosity);
+
+ /** Clears all data from the current icing instance, and reinitializes it. */
+ ResetResultProto reset();
+
+ /** Closes the current icing instance. */
+ @Override
+ void close();
+}
diff --git a/java/src/com/google/android/icing/IcingSearchEngineUtils.java b/java/src/com/google/android/icing/IcingSearchEngineUtils.java
new file mode 100644
index 0000000..0913216
--- /dev/null
+++ b/java/src/com/google/android/icing/IcingSearchEngineUtils.java
@@ -0,0 +1,471 @@
+// Copyright (C) 2019 Google LLC
+//
+// 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.google.android.icing;
+
+import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.google.android.icing.proto.DebugInfoResultProto;
+import com.google.android.icing.proto.DeleteByNamespaceResultProto;
+import com.google.android.icing.proto.DeleteByQueryResultProto;
+import com.google.android.icing.proto.DeleteBySchemaTypeResultProto;
+import com.google.android.icing.proto.DeleteResultProto;
+import com.google.android.icing.proto.GetAllNamespacesResultProto;
+import com.google.android.icing.proto.GetOptimizeInfoResultProto;
+import com.google.android.icing.proto.GetResultProto;
+import com.google.android.icing.proto.GetSchemaResultProto;
+import com.google.android.icing.proto.GetSchemaTypeResultProto;
+import com.google.android.icing.proto.InitializeResultProto;
+import com.google.android.icing.proto.OptimizeResultProto;
+import com.google.android.icing.proto.PersistToDiskResultProto;
+import com.google.android.icing.proto.PutResultProto;
+import com.google.android.icing.proto.ReportUsageResultProto;
+import com.google.android.icing.proto.ResetResultProto;
+import com.google.android.icing.proto.SearchResultProto;
+import com.google.android.icing.proto.SetSchemaResultProto;
+import com.google.android.icing.proto.StatusProto;
+import com.google.android.icing.proto.StorageInfoResultProto;
+import com.google.android.icing.proto.SuggestionResponse;
+import com.google.protobuf.ExtensionRegistryLite;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+/**
+ * Contains utility methods for IcingSearchEngine to convert byte arrays to the corresponding
+ * protos.
+ *
+ * <p>It is also being used by AppSearch dynamite 0p client APIs to convert byte arrays to the
+ * protos.
+ */
+public final class IcingSearchEngineUtils {
+ private static final String TAG = "IcingSearchEngineUtils";
+ private static final ExtensionRegistryLite EXTENSION_REGISTRY_LITE =
+ ExtensionRegistryLite.getEmptyRegistry();
+
+ private IcingSearchEngineUtils() {}
+
+ // TODO(b/240333360) Check to see if we can use one template function to replace those
+ @NonNull
+ public static InitializeResultProto byteArrayToInitializeResultProto(
+ @Nullable byte[] initializeResultBytes) {
+ if (initializeResultBytes == null) {
+ Log.e(TAG, "Received null InitializeResult from native.");
+ return InitializeResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return InitializeResultProto.parseFrom(initializeResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing InitializeResultProto.", e);
+ return InitializeResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static SetSchemaResultProto byteArrayToSetSchemaResultProto(
+ @Nullable byte[] setSchemaResultBytes) {
+ if (setSchemaResultBytes == null) {
+ Log.e(TAG, "Received null SetSchemaResultProto from native.");
+ return SetSchemaResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return SetSchemaResultProto.parseFrom(setSchemaResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing SetSchemaResultProto.", e);
+ return SetSchemaResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static GetSchemaResultProto byteArrayToGetSchemaResultProto(
+ @Nullable byte[] getSchemaResultBytes) {
+ if (getSchemaResultBytes == null) {
+ Log.e(TAG, "Received null GetSchemaResultProto from native.");
+ return GetSchemaResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return GetSchemaResultProto.parseFrom(getSchemaResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing GetSchemaResultProto.", e);
+ return GetSchemaResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static GetSchemaTypeResultProto byteArrayToGetSchemaTypeResultProto(
+ @Nullable byte[] getSchemaTypeResultBytes) {
+ if (getSchemaTypeResultBytes == null) {
+ Log.e(TAG, "Received null GetSchemaTypeResultProto from native.");
+ return GetSchemaTypeResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return GetSchemaTypeResultProto.parseFrom(getSchemaTypeResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing GetSchemaTypeResultProto.", e);
+ return GetSchemaTypeResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static PutResultProto byteArrayToPutResultProto(@Nullable byte[] putResultBytes) {
+ if (putResultBytes == null) {
+ Log.e(TAG, "Received null PutResultProto from native.");
+ return PutResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return PutResultProto.parseFrom(putResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing PutResultProto.", e);
+ return PutResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static GetResultProto byteArrayToGetResultProto(@Nullable byte[] getResultBytes) {
+ if (getResultBytes == null) {
+ Log.e(TAG, "Received null GetResultProto from native.");
+ return GetResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return GetResultProto.parseFrom(getResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing GetResultProto.", e);
+ return GetResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static ReportUsageResultProto byteArrayToReportUsageResultProto(
+ @Nullable byte[] reportUsageResultBytes) {
+ if (reportUsageResultBytes == null) {
+ Log.e(TAG, "Received null ReportUsageResultProto from native.");
+ return ReportUsageResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return ReportUsageResultProto.parseFrom(reportUsageResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing ReportUsageResultProto.", e);
+ return ReportUsageResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static GetAllNamespacesResultProto byteArrayToGetAllNamespacesResultProto(
+ @Nullable byte[] getAllNamespacesResultBytes) {
+ if (getAllNamespacesResultBytes == null) {
+ Log.e(TAG, "Received null GetAllNamespacesResultProto from native.");
+ return GetAllNamespacesResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return GetAllNamespacesResultProto.parseFrom(
+ getAllNamespacesResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing GetAllNamespacesResultProto.", e);
+ return GetAllNamespacesResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static SearchResultProto byteArrayToSearchResultProto(@Nullable byte[] searchResultBytes) {
+ if (searchResultBytes == null) {
+ Log.e(TAG, "Received null SearchResultProto from native.");
+ return SearchResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ SearchResultProto.Builder searchResultProtoBuilder =
+ SearchResultProto.newBuilder().mergeFrom(searchResultBytes, EXTENSION_REGISTRY_LITE);
+ setNativeToJavaJniLatency(searchResultProtoBuilder);
+ return searchResultProtoBuilder.build();
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing SearchResultProto.", e);
+ return SearchResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ private static void setNativeToJavaJniLatency(
+ SearchResultProto.Builder searchResultProtoBuilder) {
+ int nativeToJavaLatencyMs =
+ (int)
+ (System.currentTimeMillis()
+ - searchResultProtoBuilder.getQueryStats().getNativeToJavaStartTimestampMs());
+ searchResultProtoBuilder.setQueryStats(
+ searchResultProtoBuilder.getQueryStats().toBuilder()
+ .setNativeToJavaJniLatencyMs(nativeToJavaLatencyMs));
+ }
+
+ @NonNull
+ public static DeleteResultProto byteArrayToDeleteResultProto(@Nullable byte[] deleteResultBytes) {
+ if (deleteResultBytes == null) {
+ Log.e(TAG, "Received null DeleteResultProto from native.");
+ return DeleteResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return DeleteResultProto.parseFrom(deleteResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing DeleteResultProto.", e);
+ return DeleteResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static SuggestionResponse byteArrayToSuggestionResponse(
+ @Nullable byte[] suggestionResponseBytes) {
+ if (suggestionResponseBytes == null) {
+ Log.e(TAG, "Received null suggestionResponseBytes from native.");
+ return SuggestionResponse.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return SuggestionResponse.parseFrom(suggestionResponseBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing suggestionResponseBytes.", e);
+ return SuggestionResponse.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static DeleteByNamespaceResultProto byteArrayToDeleteByNamespaceResultProto(
+ @Nullable byte[] deleteByNamespaceResultBytes) {
+ if (deleteByNamespaceResultBytes == null) {
+ Log.e(TAG, "Received null DeleteByNamespaceResultProto from native.");
+ return DeleteByNamespaceResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return DeleteByNamespaceResultProto.parseFrom(
+ deleteByNamespaceResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing DeleteByNamespaceResultProto.", e);
+ return DeleteByNamespaceResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static DeleteBySchemaTypeResultProto byteArrayToDeleteBySchemaTypeResultProto(
+ @Nullable byte[] deleteBySchemaTypeResultBytes) {
+ if (deleteBySchemaTypeResultBytes == null) {
+ Log.e(TAG, "Received null DeleteBySchemaTypeResultProto from native.");
+ return DeleteBySchemaTypeResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return DeleteBySchemaTypeResultProto.parseFrom(
+ deleteBySchemaTypeResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing DeleteBySchemaTypeResultProto.", e);
+ return DeleteBySchemaTypeResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static DeleteByQueryResultProto byteArrayToDeleteByQueryResultProto(
+ @Nullable byte[] deleteResultBytes) {
+ if (deleteResultBytes == null) {
+ Log.e(TAG, "Received null DeleteResultProto from native.");
+ return DeleteByQueryResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return DeleteByQueryResultProto.parseFrom(deleteResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing DeleteResultProto.", e);
+ return DeleteByQueryResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static PersistToDiskResultProto byteArrayToPersistToDiskResultProto(
+ @Nullable byte[] persistToDiskResultBytes) {
+ if (persistToDiskResultBytes == null) {
+ Log.e(TAG, "Received null PersistToDiskResultProto from native.");
+ return PersistToDiskResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return PersistToDiskResultProto.parseFrom(persistToDiskResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing PersistToDiskResultProto.", e);
+ return PersistToDiskResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static OptimizeResultProto byteArrayToOptimizeResultProto(
+ @Nullable byte[] optimizeResultBytes) {
+ if (optimizeResultBytes == null) {
+ Log.e(TAG, "Received null OptimizeResultProto from native.");
+ return OptimizeResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return OptimizeResultProto.parseFrom(optimizeResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing OptimizeResultProto.", e);
+ return OptimizeResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static GetOptimizeInfoResultProto byteArrayToGetOptimizeInfoResultProto(
+ @Nullable byte[] getOptimizeInfoResultBytes) {
+ if (getOptimizeInfoResultBytes == null) {
+ Log.e(TAG, "Received null GetOptimizeInfoResultProto from native.");
+ return GetOptimizeInfoResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return GetOptimizeInfoResultProto.parseFrom(
+ getOptimizeInfoResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing GetOptimizeInfoResultProto.", e);
+ return GetOptimizeInfoResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static StorageInfoResultProto byteArrayToStorageInfoResultProto(
+ @Nullable byte[] storageInfoResultProtoBytes) {
+ if (storageInfoResultProtoBytes == null) {
+ Log.e(TAG, "Received null StorageInfoResultProto from native.");
+ return StorageInfoResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return StorageInfoResultProto.parseFrom(storageInfoResultProtoBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing GetOptimizeInfoResultProto.", e);
+ return StorageInfoResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static DebugInfoResultProto byteArrayToDebugInfoResultProto(
+ @Nullable byte[] debugInfoResultProtoBytes) {
+ if (debugInfoResultProtoBytes == null) {
+ Log.e(TAG, "Received null DebugInfoResultProto from native.");
+ return DebugInfoResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return DebugInfoResultProto.parseFrom(debugInfoResultProtoBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing DebugInfoResultProto.", e);
+ return DebugInfoResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+
+ @NonNull
+ public static ResetResultProto byteArrayToResetResultProto(@Nullable byte[] resetResultBytes) {
+ if (resetResultBytes == null) {
+ Log.e(TAG, "Received null ResetResultProto from native.");
+ return ResetResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+
+ try {
+ return ResetResultProto.parseFrom(resetResultBytes, EXTENSION_REGISTRY_LITE);
+ } catch (InvalidProtocolBufferException e) {
+ Log.e(TAG, "Error parsing ResetResultProto.", e);
+ return ResetResultProto.newBuilder()
+ .setStatus(StatusProto.newBuilder().setCode(StatusProto.Code.INTERNAL))
+ .build();
+ }
+ }
+}