Merge remote-tracking branch 'aosp/upstream-master' into androidx-master-dev

* aosp/upstream-master:
  Update Icing from upstream.

Change-Id: I057ed60aa443b3632947538c3712252d80789e35
diff --git a/.gitignore b/.gitignore
index f57bd5e..962fbd5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@
 
 # Files
 *.iml
+*.cmake.gen
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 556150a..e520663 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,75 +14,91 @@
 
 cmake_minimum_required(VERSION 3.10.2)
 
-# Build protoc with a host configuration. We need to run it on the host to create our proto
-# files.
-set(CMAKE_HOST_ARGS
-  -DBUILD_SHARED_LIBS:BOOL=${BUILD_SHARED_LIBS}
-  -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-  -DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER}
-  -DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER}
-  -DCMAKE_GENERATOR:STRING=${CMAKE_GENERATOR}
-  -DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM})
+add_definitions("-DICING_REVERSE_JNI_SEGMENTATION=1")
 
+set(
+    Protobuf_PREBUILTS_DIR
+    "${CMAKE_CURRENT_SOURCE_DIR}/../../prebuilts/protobuf")
 set(Protobuf_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../protobuf")
-set(Protobuf_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/protobuf-host")
-# Run another cmake invocation to configure the protobuf project
-execute_process(
-    COMMAND "${CMAKE_COMMAND}"
-    ${CMAKE_HOST_ARGS}
-    -H${Protobuf_SOURCE_DIR}/cmake
-    -B${Protobuf_BINARY_DIR}
-    -Dprotobuf_BUILD_TESTS:BOOL=OFF
-    RESULT_VARIABLE exec_value
-    OUTPUT_VARIABLE exec_output
-    ERROR_VARIABLE exec_output
-)
-message("Result of proto configuration: ${exec_value}. Output: ${exec_output}")
+set(Protobuf_TARGET_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/protobuf-target")
+set(Icing_PROTO_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/icing-protobuf-gen")
 
-# Run the actual build tool (ninja) to compile protoc for the host
-execute_process(
-    COMMAND "${CMAKE_MAKE_PROGRAM}" protoc
-    WORKING_DIRECTORY ${Protobuf_BINARY_DIR}
-    RESULT_VARIABLE exec_value
-    OUTPUT_VARIABLE exec_output
-    ERROR_VARIABLE exec_output
-)
-message("Result of proto build: ${exec_value}. Output: ${exec_output}")
+## Configure libprotobuf ##
+# Find the right protoc to compile our proto files
+if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Darwin")
+  set(Protobuf_PROTOC_PATH "${Protobuf_PREBUILTS_DIR}/darwin-x86_64/protoc")
+elseif(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux")
+  set(Protobuf_PROTOC_PATH "${Protobuf_PREBUILTS_DIR}/linux-x86_64/protoc")
+elseif(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows")
+  set(Protobuf_PROTOC_PATH "${Protobuf_PREBUILTS_DIR}/windows-x86/protoc.exe")
+else()
+  message(
+      FATAL_ERROR
+      "No protoc prebuilt found for host OS ${CMAKE_HOST_SYSTEM_NAME}")
+endif()
+message(STATUS "Using prebuilt protoc at: ${Protobuf_PROTOC_PATH}")
 
-# Glob Icing proto sources
+# Compile libprotobuf
+set(protobuf_BUILD_TESTS OFF CACHE BOOL "")
+add_subdirectory("${Protobuf_SOURCE_DIR}/cmake" ${Protobuf_TARGET_BINARY_DIR})
+
+# Compile libandroidicu
+set(ICU_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../icu/libandroidicu")
+set(ICU_TARGET_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/icu-target")
+add_subdirectory(${ICU_SOURCE_DIR} ${ICU_TARGET_BINARY_DIR})
+
+# Creates a file deps_name.cmake to save dependencies in it. This file should be
+# treated as part of CMakeLists.txt. This file should stay in .gitignore
+# TODO: When supporting cmake v3.12 or higher, use CONFIGURE_DEPENDS in the glob
+# and remove this section.
+function(update_deps_file deps_name deps)
+    set(DEPS_FILE ${deps_name}.cmake.gen)
+    set(CONTENT "# generated by make process.\nset(Tmp_${deps_name} ${deps})\n")
+    set(EXISTING_CONTENT "")
+    if(EXISTS ${DEPS_FILE})
+        file(READ ${DEPS_FILE} EXISTING_CONTENT)
+    endif()
+    # Compare the new contents with the existing file, if it exists and is the same
+    # we don't want to trigger a make by changing its timestamp.
+    if(NOT EXISTING_CONTENT STREQUAL CONTENT)
+        file(WRITE ${DEPS_FILE} ${CONTENT})
+    endif()
+    # Include the file so it's tracked as a generation dependency we don't
+    # need the content.
+    include(${DEPS_FILE})
+endfunction(update_deps_file)
+
+# Glob Icing proto sources. Results look like this: icing/proto/document.proto
 file(
     GLOB_RECURSE
     Icing_PROTO_FILES
-    RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
-    "icing/*.proto")
+    RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/proto"
+    "*.proto")
 message(STATUS "Icing_PROTO_FILES=${Icing_PROTO_FILES}")
 
+update_deps_file("IcingProtoFiles" "${Icing_PROTO_FILES}")
+
 # Run protoc on Icing_PROTO_FILES to generate pb.cc and pb.h files
-set(Icing_PROTO_GEN_DIR "${PROTO_GENERATED_FILES_BASE_DIR}/cpp")
+# The DEPENDS section of add_custom_command could trigger a remake if any proto
+# source file has been updated.
 file(MAKE_DIRECTORY ${Icing_PROTO_GEN_DIR})
 foreach(FILE ${Icing_PROTO_FILES})
     # Find the name of the proto file without the .proto extension
     string(REGEX REPLACE "\.proto$" "" FILE_NOEXT ${FILE})
-    execute_process(
-        COMMAND "${Protobuf_BINARY_DIR}/protoc"
-        --proto_path ${CMAKE_CURRENT_SOURCE_DIR}
-        --cpp_out ${Icing_PROTO_GEN_DIR}
-        ${FILE}
+    list(APPEND Icing_PROTO_SOURCES
+      "${Icing_PROTO_GEN_DIR}/${FILE_NOEXT}.pb.cc"
+      "${Icing_PROTO_GEN_DIR}/${FILE_NOEXT}.pb.h")
+    add_custom_command(
+        OUTPUT "${Icing_PROTO_GEN_DIR}/${FILE_NOEXT}.pb.cc"
+          "${Icing_PROTO_GEN_DIR}/${FILE_NOEXT}.pb.h"
+        COMMAND ${Protobuf_PROTOC_PATH}
+          --proto_path "${CMAKE_CURRENT_SOURCE_DIR}/proto"
+          --cpp_out ${Icing_PROTO_GEN_DIR}
+          ${FILE}
         WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-        RESULT_VARIABLE exec_value
-        OUTPUT_VARIABLE exec_output
-        ERROR_VARIABLE exec_output
+        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/proto/${FILE}
     )
-    message("Result of protoc ${FILE}: ${exec_value}. Output: ${exec_output}")
 endforeach()
-
-# Glob generated source files from running protoc
-file(
-    GLOB_RECURSE
-    Icing_PROTO_SOURCES
-    "${Icing_PROTO_GEN_DIR}/*.pb.cc"
-    "${Icing_PROTO_GEN_DIR}/*.pb.h"
-)
 message(STATUS "Icing_PROTO_SOURCES=${Icing_PROTO_SOURCES}")
 
 # Glob Icing C++ sources
@@ -98,11 +114,19 @@
     # Glob expressions
     icing/*.cc icing/*.h
 )
+
+update_deps_file("IcingCCSources" "${Icing_CC_SOURCES}")
+
 # Exclude the same types of files as Android.bp. See the comments there.
-list(FILTER Icing_CC_SOURCES EXCLUDE REGEX "^icing/.*_test\.cc$")
+list(FILTER Icing_CC_SOURCES EXCLUDE REGEX "^icing/.*[^a-zA-Z0-9]test[^a-zA-Z0-9].*$")
 list(FILTER Icing_CC_SOURCES EXCLUDE REGEX "^icing/.*_benchmark\.cc$")
+list(FILTER Icing_CC_SOURCES EXCLUDE REGEX "^icing/helpers/icu/.*$")
 list(FILTER Icing_CC_SOURCES EXCLUDE REGEX "^icing/testing/.*$")
+list(FILTER Icing_CC_SOURCES EXCLUDE REGEX "^icing/tokenization/icu/.*$")
+list(FILTER Icing_CC_SOURCES EXCLUDE REGEX "^icing/tokenization/simple/.*$")
 list(FILTER Icing_CC_SOURCES EXCLUDE REGEX "^icing/tools/.*$")
+list(FILTER Icing_CC_SOURCES EXCLUDE REGEX "^icing/transform/icu/.*$")
+list(FILTER Icing_CC_SOURCES EXCLUDE REGEX "^icing/transform/simple/.*$")
 message(STATUS "Icing_CC_SOURCES=${Icing_CC_SOURCES}")
 
 add_library(
@@ -119,3 +143,5 @@
 target_include_directories(icing PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
 target_include_directories(icing PRIVATE ${Icing_PROTO_GEN_DIR})
 target_include_directories(icing PRIVATE "${Protobuf_SOURCE_DIR}/src")
+target_include_directories(icing PRIVATE "${ICU_SOURCE_DIR}/include")
+target_link_libraries(icing protobuf::libprotobuf libandroidicu log)
diff --git a/build.gradle b/build.gradle
index 30265cd..437f57f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -14,63 +14,55 @@
  * limitations under the License.
  */
 
+import static androidx.build.SupportConfig.*
+import static androidx.build.dependencies.DependenciesKt.*
+
 buildscript {
-    boolean unbundleBuild = (new File('unbundled-build')).exists()
-    repositories {
-        maven { url '../../prebuilts/androidx/external' }
-        if (unbundleBuild) {
-            jcenter()
-        }
-    }
     dependencies {
-        classpath('gradle.plugin.com.google.protobuf:protobuf-gradle-plugin:0.8.8')
+        classpath('gradle.plugin.com.google.protobuf:protobuf-gradle-plugin:0.8.13')
     }
 }
 
-apply plugin: 'AndroidXPlugin'
-apply plugin: 'com.android.library'
-apply plugin: 'com.google.protobuf'
-apply plugin: 'idea'
-
-def protoGeneratedFilesBaseDir = "${project.buildDir}/generated/source/proto"
+plugins {
+    id('com.android.library')
+    id('com.google.protobuf')
+}
 
 android {
+    buildToolsVersion BUILD_TOOLS_VERSION
+    compileSdkVersion COMPILE_SDK_VERSION
     defaultConfig {
-        externalNativeBuild {
-            cmake {
-                arguments "-DPROTO_GENERATED_FILES_BASE_DIR=${protoGeneratedFilesBaseDir}"
-                cppFlags "-std=c++17"
-                arguments "-DCMAKE_VERBOSE_MAKEFILE=ON"
-                targets "icing"
-            }
-        }
+        minSdkVersion DEFAULT_MIN_SDK_VERSION
+        targetSdkVersion TARGET_SDK_VERSION
+        testInstrumentationRunner INSTRUMENTATION_RUNNER
     }
-
+    compileOptions {
+        sourceCompatibility = JavaVersion.VERSION_1_8
+        targetCompatibility = JavaVersion.VERSION_1_8
+    }
     sourceSets {
         main {
+            java.srcDir 'java/src/'
             manifest.srcFile 'AndroidManifest.xml'
-            proto {
-                srcDir '.'
-                include '**/*.proto'
-            }
+            proto.srcDir 'proto/'
         }
-    }
-
-    externalNativeBuild {
-        cmake {
-            version '3.10.2'
-            // TODO(b/149853706): Uncomment this line once the lib fully compiles under cmake
-            //path 'CMakeLists.txt'
-        }
+        // TODO(b/161205849): Re-enable this test once icing nativeLib is no longer being built
+        //  inside appsearch:appsearch.
+        //androidTest.java.srcDir 'java/tests/instrumentation/'
     }
 }
 
 dependencies {
-    api('com.google.protobuf:protobuf-javalite:3.10.0')
+    api('androidx.annotation:annotation:1.1.0')
+
+    implementation('com.google.protobuf:protobuf-javalite:3.10.0')
+
+    androidTestImplementation(ANDROIDX_TEST_CORE)
+    androidTestImplementation(ANDROIDX_TEST_RULES)
+    androidTestImplementation(TRUTH)
 }
 
 protobuf {
-    generatedFilesBaseDir = protoGeneratedFilesBaseDir
     protoc {
         artifact = 'com.google.protobuf:protoc:3.10.0'
     }
@@ -85,3 +77,27 @@
         }
     }
 }
+
+// Create export artifact for all variants (debug/release) for JarJaring
+android.libraryVariants.all { variant ->
+    def variantName = variant.name
+    def suffix = variantName.capitalize()
+    def exportJarTask = tasks.register("exportJar${suffix}", Jar) {
+        archiveBaseName.set("icing-${variantName}")
+
+        // The proto-lite dependency includes .proto files, which are not used by icing. When apps
+        // depend on appsearch as well as proto-lite directly, these files conflict since jarjar
+        // only renames the java classes. Remove them here since they are unused.
+        // Expand the jar and remove any .proto files.
+        from(zipTree(configurations.detachedConfiguration(
+                dependencies.create(PROTOBUF_LITE)).getSingleFile())) {
+            exclude("**/*.proto")
+        }
+
+        from files(variant.javaCompileProvider.get().destinationDir)
+        dependsOn variant.javaCompileProvider.get()
+    }
+
+    def exportConfiguration = configurations.register("export${suffix}")
+    artifacts.add(exportConfiguration.name, exportJarTask.flatMap { it.archiveFile })
+}
diff --git a/icing/result/result-retriever.cc b/icing/result/result-retriever.cc
index ff6320b..a86c129 100644
--- a/icing/result/result-retriever.cc
+++ b/icing/result/result-retriever.cc
@@ -30,8 +30,9 @@
 
 namespace {
 
-void Project(const std::vector<ProjectionTree::Node>& projection_tree,
-             proto2::RepeatedPtrField<PropertyProto>* properties) {
+void Project(
+    const std::vector<ProjectionTree::Node>& projection_tree,
+    google::protobuf::RepeatedPtrField<PropertyProto>* properties) {
   int num_kept = 0;
   for (int cur_pos = 0; cur_pos < properties->size(); ++cur_pos) {
     PropertyProto* prop = properties->Mutable(cur_pos);
diff --git a/java/src/com/google/android/icing/BreakIteratorBatcher.java b/java/src/com/google/android/icing/BreakIteratorBatcher.java
index 2b87327..58efbfc 100644
--- a/java/src/com/google/android/icing/BreakIteratorBatcher.java
+++ b/java/src/com/google/android/icing/BreakIteratorBatcher.java
@@ -14,6 +14,9 @@
 
 package com.google.android.icing;
 
+import androidx.annotation.NonNull;
+import androidx.annotation.RestrictTo;
+
 import java.text.BreakIterator;
 import java.util.ArrayList;
 import java.util.List;
@@ -35,17 +38,20 @@
  * utf16Boundaries = brkItrBatcher.next(5);
  * assertThat(utf16Boundaries).asList().containsExactly(9);
  * }</pre>
+ *
+ * @hide
  */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
 public class BreakIteratorBatcher {
 
   private final BreakIterator iterator;
 
-  public BreakIteratorBatcher(Locale locale) {
+  public BreakIteratorBatcher(@NonNull Locale locale) {
     this.iterator = BreakIterator.getWordInstance(locale);
   }
 
   /* Direct calls to BreakIterator */
-  public void setText(String text) {
+  public void setText(@NonNull String text) {
     iterator.setText(text);
   }
 
@@ -67,6 +73,7 @@
    * the end of the text (returns BreakIterator#DONE), then only the results of the previous calls
    * in that batch will be returned.
    */
+  @NonNull
   public int[] next(int batchSize) {
     List<Integer> breakIndices = new ArrayList<>(batchSize);
     for (int i = 0; i < batchSize; ++i) {
diff --git a/java/src/com/google/android/icing/IcingSearchEngine.java b/java/src/com/google/android/icing/IcingSearchEngine.java
index 0902921..cac9fcd 100644
--- a/java/src/com/google/android/icing/IcingSearchEngine.java
+++ b/java/src/com/google/android/icing/IcingSearchEngine.java
@@ -40,8 +40,8 @@
 import com.google.android.icing.proto.SetSchemaResultProto;
 import com.google.android.icing.proto.StatusProto;
 import com.google.android.icing.proto.UsageReport;
-import com.google.android.icing.protobuf.ExtensionRegistryLite;
-import com.google.android.icing.protobuf.InvalidProtocolBufferException;
+import com.google.protobuf.ExtensionRegistryLite;
+import com.google.protobuf.InvalidProtocolBufferException;
 
 /** Java wrapper to access native APIs in external/icing/icing/icing-search-engine.h */
 public final class IcingSearchEngine {
diff --git a/nativeLib/build.gradle b/nativeLib/build.gradle
new file mode 100644
index 0000000..6b30451
--- /dev/null
+++ b/nativeLib/build.gradle
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO(b/161205849): We've had to move libicing.so compilation into appsearch:appsearch to get
+//  it included into the exported aar. Find a proper solution for bundling libicing.so into
+//  appsearch-release.aar and move compilation of libicing.so back into the external/icing tree.