Merge "Use jarjar on preferences.proto to solve the issue with diamond dependencies on proto_lite runtime." into androidx-master-dev
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index a9d468c..554dd59 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -120,6 +120,8 @@
const val PROTOBUF_COMPILER = "com.google.protobuf:protoc:3.10.0"
const val PROTOBUF_LITE = "com.google.protobuf:protobuf-javalite:3.10.0"
+const val JARJAR = "org.anarres.jarjar:jarjar-gradle:1.0.1"
+
// The following versions change depending on whether we are in the main or ui project - the
// specific versions are configured in build_dependencies.gradle as they are needed during
// buildSrc configuration. They are then set here in AndroidXPlugin when configuring the root
diff --git a/datastore/datastore-preferences/build.gradle b/datastore/datastore-preferences/build.gradle
index 4954606..a4ba37e 100644
--- a/datastore/datastore-preferences/build.gradle
+++ b/datastore/datastore-preferences/build.gradle
@@ -16,22 +16,39 @@
import static androidx.build.dependencies.DependenciesKt.*
import androidx.build.LibraryGroups
-import androidx.build.AndroidXExtension
import androidx.build.Publish
+buildscript {
+ dependencies {
+ classpath JARJAR
+ }
+}
+
plugins {
id("AndroidXPlugin")
id("com.android.library")
id("kotlin-android")
- id("com.google.protobuf")
+ id("org.anarres.jarjar")
+}
+
+
+// Include :datastore-preferences-proto
+android.libraryVariants.all { variant ->
+ def variantName = variant.name
+ def suffix = variantName.capitalize()
+ def jarjarConfigName = "jarjar${suffix}"
+ def jarjarConf = configurations.register(jarjarConfigName)
+ // Treat datastore-preferences-proto as a local jar and package it inside the aar
+ dependencies.add(jarjarConfigName, project.dependencies.project(
+ path: ":datastore:datastore-preferences:datastore-preferences-proto",
+ configuration: jarjarConfigName))
+ dependencies.add("${variantName}Implementation", files(jarjarConf))
}
dependencies {
api(KOTLIN_STDLIB)
api(project(":datastore:datastore-core"))
- implementation(PROTOBUF_LITE)
-
testImplementation(JUNIT)
testImplementation(KOTLIN_COROUTINES_TEST)
testImplementation(KOTLIN_TEST)
@@ -43,26 +60,6 @@
androidTestImplementation(ANDROIDX_TEST_CORE)
}
-protobuf {
- protoc {
- artifact = PROTOBUF_COMPILER
- }
-
- // Generates the java proto-lite code for the protos in this project. See
- // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
- // for more information.
- generateProtoTasks {
- all().each { task ->
- task.builtins {
- java {
- option 'lite'
- }
- }
- }
- }
-}
-
-
androidx {
name = "Android Preferences DataStore"
publish = Publish.SNAPSHOT_AND_RELEASE
diff --git a/datastore/datastore-preferences/datastore-preferences-proto/build.gradle b/datastore/datastore-preferences/datastore-preferences-proto/build.gradle
new file mode 100644
index 0000000..d6e367d
--- /dev/null
+++ b/datastore/datastore-preferences/datastore-preferences-proto/build.gradle
@@ -0,0 +1,118 @@
+/*
+ * Copyright 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.
+ */
+
+import org.anarres.gradle.plugin.jarjar.JarjarTask
+
+import static androidx.build.dependencies.DependenciesKt.*
+import androidx.build.LibraryGroups
+import androidx.build.Publish
+
+
+buildscript {
+ dependencies {
+ classpath 'org.anarres.jarjar:jarjar-gradle:1.0.1'
+ }
+}
+
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("kotlin-android")
+ id("com.google.protobuf")
+}
+
+apply plugin: 'org.anarres.jarjar'
+
+
+dependencies {
+ implementation(PROTOBUF_LITE)
+ api(project(":datastore:datastore-core"))
+}
+
+protobuf {
+ protoc {
+ artifact = PROTOBUF_COMPILER
+ }
+
+ // Generates the java proto-lite code for the protos in this project. See
+ // https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation
+ // for more information.
+ generateProtoTasks {
+ all().each { task ->
+ task.builtins {
+ java {
+ option 'lite'
+ }
+ }
+ }
+ }
+}
+
+android.libraryVariants.all { variant ->
+ def variantName = variant.name
+ def suffix = variantName.capitalize()
+ def jarjarTask = tasks.register("jarjar${suffix}", JarjarTask) {
+ destinationName "datastore-preferences-proto-${variantName}-jarjar.jar"
+ dependsOn protoLiteJarWithoutProtoFiles
+ from(files(protoLiteJarWithoutProtoFiles.archiveFile.get().getAsFile()))
+
+ from files(variant.javaCompileProvider.get().destinationDir)
+ dependsOn variant.javaCompileProvider.get()
+
+ if (suffix == "Debug") {
+ from(files(compileDebugKotlin.outputs.files))
+ } else if (suffix == "Release") {
+ from(files(compileReleaseKotlin.outputs.files))
+ } else {
+ throw IllegalStateException("Expected either debug or release variant.")
+ }
+ classRename 'com.google.protobuf.**', 'androidx.datastore.preferences.protobuf.@1'
+ }
+
+ def jarjarConf = configurations.register("jarjar${suffix}")
+ artifacts.add("${jarjarConf.name}", jarjarTask.get().destinationPath) {
+ name "datastore-preferences-proto-${variantName}-jarjar"
+ type 'jar'
+ builtBy jarjarTask
+ }
+}
+
+// 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.
+tasks.register("protoLiteJarWithoutProtoFiles", Jar) {
+ // Get proto lite jar as a file.
+ def jarFile = configurations.detachedConfiguration(dependencies.create
+ (PROTOBUF_LITE)).getSingleFile()
+
+ // Expand the jar and remove any .proto files.
+ from(zipTree(jarFile)) {
+ exclude("**/*.proto")
+ }
+
+
+ into 'datastore-preferences-proto-lite-dep'
+}
+
+androidx {
+ name = "Android Preferences DataStore Proto"
+ publish = Publish.NONE
+ mavenGroup = LibraryGroups.DATASTORE
+ inceptionYear = "2020"
+ description = "Jarjar the generated proto and proto-lite dependency for use by " +
+ "datastore-preferences."
+}
diff --git a/datastore/datastore-preferences/datastore-preferences-proto/src/main/AndroidManifest.xml b/datastore/datastore-preferences/datastore-preferences-proto/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..384c619
--- /dev/null
+++ b/datastore/datastore-preferences/datastore-preferences-proto/src/main/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="androidx.datastore.preferences.proto">
+
+</manifest>
\ No newline at end of file
diff --git a/datastore/datastore-preferences/datastore-preferences-proto/src/main/java/androidx/datastore/preferences/PreferencesMapCompat.kt b/datastore/datastore-preferences/datastore-preferences-proto/src/main/java/androidx/datastore/preferences/PreferencesMapCompat.kt
new file mode 100644
index 0000000..b7a00c6
--- /dev/null
+++ b/datastore/datastore-preferences/datastore-preferences-proto/src/main/java/androidx/datastore/preferences/PreferencesMapCompat.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright 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.
+ */
+
+package androidx.datastore.preferences
+
+import androidx.datastore.CorruptionException
+import com.google.protobuf.InvalidProtocolBufferException
+import java.io.InputStream
+
+/**
+ * Read PreferenceMap proto but convert InvalidProtocolBufferExceptions to CorruptionExceptions.
+ * @hide
+ */
+class PreferencesMapCompat {
+ companion object {
+ fun readFrom(input: InputStream): PreferencesProto.PreferenceMap {
+ return try {
+ PreferencesProto.PreferenceMap.parseFrom(input)
+ } catch (ipbe: InvalidProtocolBufferException) {
+ throw CorruptionException("Unable to parse preferences proto.", ipbe)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/datastore/datastore-preferences/src/main/proto/preferences.proto b/datastore/datastore-preferences/datastore-preferences-proto/src/main/proto/preferences.proto
similarity index 100%
rename from datastore/datastore-preferences/src/main/proto/preferences.proto
rename to datastore/datastore-preferences/datastore-preferences-proto/src/main/proto/preferences.proto
diff --git a/datastore/datastore-preferences/src/main/java/androidx/datastore/preferences/PreferencesSerializer.kt b/datastore/datastore-preferences/src/main/java/androidx/datastore/preferences/PreferencesSerializer.kt
index 44949c2..2f4fa2c 100644
--- a/datastore/datastore-preferences/src/main/java/androidx/datastore/preferences/PreferencesSerializer.kt
+++ b/datastore/datastore-preferences/src/main/java/androidx/datastore/preferences/PreferencesSerializer.kt
@@ -21,7 +21,6 @@
import androidx.datastore.preferences.PreferencesProto.Value
import androidx.datastore.preferences.PreferencesProto.StringSet
import androidx.datastore.Serializer
-import com.google.protobuf.InvalidProtocolBufferException
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
@@ -37,14 +36,7 @@
@Throws(IOException::class, CorruptionException::class)
override fun readFrom(input: InputStream): Preferences {
- val preferencesProto = try {
- PreferenceMap.parseFrom(input)
- } catch (invalidProtocolBufferException: InvalidProtocolBufferException) {
- throw CorruptionException(
- "Unable to parse preferences proto.",
- invalidProtocolBufferException
- )
- }
+ val preferencesProto = PreferencesMapCompat.readFrom(input)
val preferencesMap = preferencesProto.preferencesMap.mapValues {
convertProtoToObject(it.value)
diff --git a/settings.gradle b/settings.gradle
index 9945728..ff95a5c 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -141,6 +141,8 @@
includeProject(":customview:customview", "customview/customview")
includeProject(":datastore:datastore-core", "datastore/datastore-core")
includeProject(":datastore:datastore-preferences", "datastore/datastore-preferences")
+includeProject(":datastore:datastore-preferences:datastore-preferences-proto",
+ "datastore/datastore-preferences/datastore-preferences-proto")
includeProject(":datastore:datastore-proto", "datastore/datastore-proto")
includeProject(":datastore:datastore-sampleapp", "datastore/datastore-sampleapp")
includeProject(":documentfile:documentfile", "documentfile/documentfile")
@@ -210,7 +212,7 @@
includeProject(":lifecycle:lifecycle-service", "lifecycle/lifecycle-service")
includeProject(":lifecycle:lifecycle-viewmodel", "lifecycle/lifecycle-viewmodel")
includeProject(":lifecycle:lifecycle-viewmodel-ktx", "lifecycle/lifecycle-viewmodel-ktx")
-includeProject(":lifecycle:lifecycle-viewmodel-savedstate","lifecycle/lifecycle-viewmodel-savedstate")
+includeProject(":lifecycle:lifecycle-viewmodel-savedstate", "lifecycle/lifecycle-viewmodel-savedstate")
includeProject(":lint-demos:lint-demo-appcompat", "lint-demos/lint-demo-appcompat")
includeProject(":loader:loader", "loader/loader")
includeProject(":loader:loader-ktx", "loader/loader-ktx")