Merge changes If022a8f1,Ibb836331,I106d2eba,Ie2541f80,I430f47de into pi-preview1-androidx-dev
am: 268b6f5307
Change-Id: I73091b335582596deb3b65335cb020c03a0c62cb
diff --git a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
index 32eee0b..b08787e 100644
--- a/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
+++ b/buildSrc/src/main/kotlin/androidx/build/dependencies/Dependencies.kt
@@ -41,13 +41,7 @@
const val RX_JAVA = "io.reactivex.rxjava2:rxjava:2.0.6"
const val TEST_RUNNER = "com.android.support.test:runner:1.0.1"
const val TEST_RULES = "com.android.support.test:rules:1.0.1"
-
-const val ESPRESSO_CONTRIB_TMP = "com.android.temp.support.test.espresso:espresso-contrib:3.0.1"
-const val ESPRESSO_CORE_TMP = "com.android.temp.support.test.espresso:espresso-core:3.0.1"
-const val TEST_RUNNER_TMP = "com.android.temp.support.test:runner:1.0.1"
-const val TEST_RULES_TMP = "com.android.temp.support.test:rules:1.0.1"
-
-
+const val TRUTH = "com.google.truth:truth:0.34"
/**
* this Xerial version is newer than we want but we need it to fix
* https://github.com/xerial/sqlite-jdbc/issues/97
@@ -55,6 +49,11 @@
*/
const val XERIAL = "org.xerial:sqlite-jdbc:3.20.1"
+const val ESPRESSO_CONTRIB_TMP = "com.android.temp.support.test.espresso:espresso-contrib:3.0.1"
+const val ESPRESSO_CORE_TMP = "com.android.temp.support.test.espresso:espresso-core:3.0.1"
+const val TEST_RUNNER_TMP = "com.android.temp.support.test:runner:1.0.1"
+const val TEST_RULES_TMP = "com.android.temp.support.test:rules:1.0.1"
+
// Support library dependencies needed for projects that compile against prebuilt versions
// instead of source directly.
// NOTE: _27 versions exist for modules that have opted-in to 27, and tests that depend on those
diff --git a/car/res/drawable/car_button_ripple_background.xml b/car/res/drawable/car_button_ripple_background.xml
new file mode 100644
index 0000000..13d0a49
--- /dev/null
+++ b/car/res/drawable/car_button_ripple_background.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+<ripple
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/car_card_ripple_background" />
diff --git a/car/res/drawable/car_button_ripple_background_day.xml b/car/res/drawable/car_button_ripple_background_day.xml
new file mode 100644
index 0000000..16b1d0c
--- /dev/null
+++ b/car/res/drawable/car_button_ripple_background_day.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+<ripple
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/car_card_ripple_background_dark" />
diff --git a/car/res/drawable/car_button_ripple_background_inverse.xml b/car/res/drawable/car_button_ripple_background_inverse.xml
new file mode 100644
index 0000000..660dbcd
--- /dev/null
+++ b/car/res/drawable/car_button_ripple_background_inverse.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+<ripple
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/car_card_ripple_background_inverse" />
diff --git a/car/res/drawable/car_button_ripple_background_night.xml b/car/res/drawable/car_button_ripple_background_night.xml
new file mode 100644
index 0000000..6160768
--- /dev/null
+++ b/car/res/drawable/car_button_ripple_background_night.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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.
+ -->
+<ripple
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/car_card_ripple_background_light" />
diff --git a/car/res/layout/car_paged_scrollbar_buttons.xml b/car/res/layout/car_paged_scrollbar_buttons.xml
index b126b48..e982b66 100644
--- a/car/res/layout/car_paged_scrollbar_buttons.xml
+++ b/car/res/layout/car_paged_scrollbar_buttons.xml
@@ -22,7 +22,7 @@
android:gravity="center"
android:orientation="vertical">
- <ImageView
+ <ImageButton
android:id="@+id/page_up"
android:layout_width="@dimen/car_scroll_bar_button_size"
android:layout_height="@dimen/car_scroll_bar_button_size"
@@ -47,7 +47,7 @@
android:background="@drawable/car_scrollbar_thumb" />
</FrameLayout>
- <ImageView
+ <ImageButton
android:id="@+id/page_down"
android:layout_width="@dimen/car_scroll_bar_button_size"
android:layout_height="@dimen/car_scroll_bar_button_size"
diff --git a/car/src/main/java/androidx/car/widget/PagedScrollBarView.java b/car/src/main/java/androidx/car/widget/PagedScrollBarView.java
index ef0b3c2..8d26916 100644
--- a/car/src/main/java/androidx/car/widget/PagedScrollBarView.java
+++ b/car/src/main/java/androidx/car/widget/PagedScrollBarView.java
@@ -248,22 +248,22 @@
case DayNightStyle.AUTO:
tintResId = R.color.car_tint;
thumbColorResId = R.color.car_scrollbar_thumb;
- upDownBackgroundResId = R.drawable.car_card_ripple_background;
+ upDownBackgroundResId = R.drawable.car_button_ripple_background;
break;
case DayNightStyle.AUTO_INVERSE:
tintResId = R.color.car_tint_inverse;
thumbColorResId = R.color.car_scrollbar_thumb_inverse;
- upDownBackgroundResId = R.drawable.car_card_ripple_background_inverse;
+ upDownBackgroundResId = R.drawable.car_button_ripple_background_inverse;
break;
case DayNightStyle.FORCE_NIGHT:
tintResId = R.color.car_tint_light;
thumbColorResId = R.color.car_scrollbar_thumb_light;
- upDownBackgroundResId = R.drawable.car_card_ripple_background_night;
+ upDownBackgroundResId = R.drawable.car_button_ripple_background_night;
break;
case DayNightStyle.FORCE_DAY:
tintResId = R.color.car_tint_dark;
thumbColorResId = R.color.car_scrollbar_thumb_dark;
- upDownBackgroundResId = R.drawable.car_card_ripple_background_day;
+ upDownBackgroundResId = R.drawable.car_button_ripple_background_day;
break;
default:
throw new IllegalArgumentException("Unknown DayNightStyle: " + mDayNightStyle);
diff --git a/collection-ktx/OWNERS b/collection-ktx/OWNERS
new file mode 100644
index 0000000..e450f4c
--- /dev/null
+++ b/collection-ktx/OWNERS
@@ -0,0 +1 @@
+jakew@google.com
diff --git a/collection-ktx/build.gradle b/collection-ktx/build.gradle
new file mode 100644
index 0000000..83944f2
--- /dev/null
+++ b/collection-ktx/build.gradle
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2018 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 static androidx.build.dependencies.DependenciesKt.*
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+
+plugins {
+ id("SupportKotlinLibraryPlugin")
+}
+
+dependencies {
+ compile(project(":collection"))
+ compile(KOTLIN_STDLIB)
+ testCompile(JUNIT)
+ testCompile(TRUTH)
+ testCompile(project(":internal-testutils-ktx"))
+}
+
+supportLibrary {
+ name = "Collections Kotlin Extensions"
+ publish = true
+ mavenVersion = LibraryVersions.SUPPORT_LIBRARY
+ mavenGroup = LibraryGroups.COLLECTION
+ inceptionYear = "2018"
+ description = "Kotlin extensions for 'collection' artifact"
+}
diff --git a/collection-ktx/src/main/java/androidx/collection/ArrayMap.kt b/collection-ktx/src/main/java/androidx/collection/ArrayMap.kt
new file mode 100644
index 0000000..8f3299e
--- /dev/null
+++ b/collection-ktx/src/main/java/androidx/collection/ArrayMap.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+@file:Suppress("NOTHING_TO_INLINE") // Aliases to public API.
+
+package androidx.collection
+
+/** Returns an empty new [ArrayMap]. */
+inline fun <K, V> arrayMapOf(): ArrayMap<K, V> = ArrayMap()
+
+/**
+ * Returns a new [ArrayMap] with the specified contents, given as a list of pairs where the first
+ * component is the key and the second component is the value.
+ *
+ * If multiple pairs have the same key, the resulting map will contain the value from the last of
+ * those pairs.
+ */
+fun <K, V> arrayMapOf(vararg pairs: Pair<K, V>): ArrayMap<K, V> {
+ val map = ArrayMap<K, V>(pairs.size)
+ for (pair in pairs) {
+ map[pair.first] = pair.second
+ }
+ return map
+}
diff --git a/collection-ktx/src/main/java/androidx/collection/ArraySet.kt b/collection-ktx/src/main/java/androidx/collection/ArraySet.kt
new file mode 100644
index 0000000..07b4be7
--- /dev/null
+++ b/collection-ktx/src/main/java/androidx/collection/ArraySet.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+@file:Suppress("NOTHING_TO_INLINE") // Aliases to public API.
+
+package androidx.collection
+
+/** Returns an empty new [ArraySet]. */
+inline fun <T> arraySetOf(): ArraySet<T> = ArraySet()
+
+/** Returns a new [ArraySet] with the specified contents. */
+fun <T> arraySetOf(vararg values: T): ArraySet<T> {
+ val set = ArraySet<T>(values.size)
+ @Suppress("LoopToCallChain") // Causes needless copy to a list.
+ for (value in values) {
+ set.add(value)
+ }
+ return set
+}
diff --git a/collection-ktx/src/main/java/androidx/collection/LongSparseArray.kt b/collection-ktx/src/main/java/androidx/collection/LongSparseArray.kt
new file mode 100644
index 0000000..fd6201a
--- /dev/null
+++ b/collection-ktx/src/main/java/androidx/collection/LongSparseArray.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+@file:Suppress("NOTHING_TO_INLINE") // Aliases to public API.
+
+package androidx.collection
+
+/** Returns the number of key/value pairs in the collection. */
+inline val <T> LongSparseArray<T>.size get() = size()
+
+/** Returns true if the collection contains [key]. */
+inline operator fun <T> LongSparseArray<T>.contains(key: Long) = indexOfKey(key) >= 0
+
+/** Allows the use of the index operator for storing values in the collection. */
+inline operator fun <T> LongSparseArray<T>.set(key: Long, value: T) = put(key, value)
+
+/** Creates a new collection by adding or replacing entries from [other]. */
+operator fun <T> LongSparseArray<T>.plus(other: LongSparseArray<T>): LongSparseArray<T> {
+ val new = LongSparseArray<T>(size() + other.size())
+ new.putAll(this)
+ new.putAll(other)
+ return new
+}
+
+/** Returns true if the collection contains [key]. */
+inline fun <T> LongSparseArray<T>.containsKey(key: Long) = indexOfKey(key) >= 0
+
+/** Returns true if the collection contains [value]. */
+inline fun <T> LongSparseArray<T>.containsValue(value: T) = indexOfValue(value) != -1
+
+/** Return the value corresponding to [key], or [defaultValue] when not present. */
+inline fun <T> LongSparseArray<T>.getOrDefault(key: Long, defaultValue: T) =
+ get(key) ?: defaultValue
+
+/** Return the value corresponding to [key], or from [defaultValue] when not present. */
+inline fun <T> LongSparseArray<T>.getOrElse(key: Long, defaultValue: () -> T) =
+ get(key) ?: defaultValue()
+
+/** Return true when the collection contains elements. */
+inline fun <T> LongSparseArray<T>.isNotEmpty() = size() != 0
+
+/** Removes the entry for [key] only if it is mapped to [value]. */
+fun <T> LongSparseArray<T>.remove(key: Long, value: T): Boolean {
+ val index = indexOfKey(key)
+ if (index != -1 && value == valueAt(index)) {
+ removeAt(index)
+ return true
+ }
+ return false
+}
+
+/** Update this collection by adding or replacing entries from [other]. */
+fun <T> LongSparseArray<T>.putAll(other: LongSparseArray<T>) = other.forEach(::put)
+
+/** Performs the given [action] for each key/value entry. */
+inline fun <T> LongSparseArray<T>.forEach(action: (key: Long, value: T) -> Unit) {
+ for (index in 0 until size()) {
+ action(keyAt(index), valueAt(index))
+ }
+}
+
+/** Return an iterator over the collection's keys. */
+fun <T> LongSparseArray<T>.keyIterator(): LongIterator = object : LongIterator() {
+ var index = 0
+ override fun hasNext() = index < size()
+ override fun nextLong() = keyAt(index++)
+}
+
+/** Return an iterator over the collection's values. */
+fun <T> LongSparseArray<T>.valueIterator(): Iterator<T> = object : Iterator<T> {
+ var index = 0
+ override fun hasNext() = index < size()
+ override fun next() = valueAt(index++)
+}
diff --git a/collection-ktx/src/main/java/androidx/collection/LruCache.kt b/collection-ktx/src/main/java/androidx/collection/LruCache.kt
new file mode 100644
index 0000000..554a012
--- /dev/null
+++ b/collection-ktx/src/main/java/androidx/collection/LruCache.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 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.collection
+
+/**
+ * Creates an [LruCache] with the given parameters.
+ *
+ * @param maxSize for caches that do not specify [sizeOf], this is
+ * the maximum number of entries in the cache. For all other caches,
+ * this is the maximum sum of the sizes of the entries in this cache.
+ * @param sizeOf function that returns the size of the entry for key and value in
+ * user-defined units. The default implementation returns 1.
+ * @param create a create called after a cache miss to compute a value for the corresponding key.
+ * Returns the computed value or null if no value can be computed. The default implementation
+ * returns null.
+ * @param onEntryRemoved a function called for entries that have been evicted or removed.
+ *
+ * @see LruCache.sizeOf
+ * @see LruCache.create
+ * @see LruCache.entryRemoved
+ */
+inline fun <K : Any, V : Any> lruCache(
+ maxSize: Int,
+ crossinline sizeOf: (key: K, value: V) -> Int = { _, _ -> 1 },
+ @Suppress("USELESS_CAST") // https://youtrack.jetbrains.com/issue/KT-21946
+ crossinline create: (key: K) -> V? = { null as V? },
+ crossinline onEntryRemoved: (evicted: Boolean, key: K, oldValue: V, newValue: V?) -> Unit =
+ { _, _, _, _ -> }
+): LruCache<K, V> {
+ return object : LruCache<K, V>(maxSize) {
+ override fun sizeOf(key: K, value: V) = sizeOf(key, value)
+ override fun create(key: K) = create(key)
+ override fun entryRemoved(evicted: Boolean, key: K, oldValue: V, newValue: V?) {
+ onEntryRemoved(evicted, key, oldValue, newValue)
+ }
+ }
+}
diff --git a/collection-ktx/src/main/java/androidx/collection/SparseArray.kt b/collection-ktx/src/main/java/androidx/collection/SparseArray.kt
new file mode 100644
index 0000000..e1d2382
--- /dev/null
+++ b/collection-ktx/src/main/java/androidx/collection/SparseArray.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+@file:Suppress("NOTHING_TO_INLINE") // Aliases to public API.
+
+package androidx.collection
+
+/** Returns the number of key/value pairs in the collection. */
+inline val <T> SparseArrayCompat<T>.size get() = size()
+
+/** Returns true if the collection contains [key]. */
+inline operator fun <T> SparseArrayCompat<T>.contains(key: Int) = indexOfKey(key) >= 0
+
+/** Allows the use of the index operator for storing values in the collection. */
+inline operator fun <T> SparseArrayCompat<T>.set(key: Int, value: T) = put(key, value)
+
+/** Creates a new collection by adding or replacing entries from [other]. */
+operator fun <T> SparseArrayCompat<T>.plus(other: SparseArrayCompat<T>): SparseArrayCompat<T> {
+ val new = SparseArrayCompat<T>(size() + other.size())
+ new.putAll(this)
+ new.putAll(other)
+ return new
+}
+
+/** Returns true if the collection contains [key]. */
+inline fun <T> SparseArrayCompat<T>.containsKey(key: Int) = indexOfKey(key) >= 0
+
+/** Returns true if the collection contains [value]. */
+inline fun <T> SparseArrayCompat<T>.containsValue(value: T) = indexOfValue(value) != -1
+
+/** Return the value corresponding to [key], or [defaultValue] when not present. */
+inline fun <T> SparseArrayCompat<T>.getOrDefault(key: Int, defaultValue: T) =
+ get(key) ?: defaultValue
+
+/** Return the value corresponding to [key], or from [defaultValue] when not present. */
+inline fun <T> SparseArrayCompat<T>.getOrElse(key: Int, defaultValue: () -> T) =
+ get(key) ?: defaultValue()
+
+/** Return true when the collection contains elements. */
+inline fun <T> SparseArrayCompat<T>.isNotEmpty() = size() != 0
+
+/** Removes the entry for [key] only if it is mapped to [value]. */
+fun <T> SparseArrayCompat<T>.remove(key: Int, value: T): Boolean {
+ val index = indexOfKey(key)
+ if (index != -1 && value == valueAt(index)) {
+ removeAt(index)
+ return true
+ }
+ return false
+}
+
+/** Update this collection by adding or replacing entries from [other]. */
+fun <T> SparseArrayCompat<T>.putAll(other: SparseArrayCompat<T>) = other.forEach(::put)
+
+/** Performs the given [action] for each key/value entry. */
+inline fun <T> SparseArrayCompat<T>.forEach(action: (key: Int, value: T) -> Unit) {
+ for (index in 0 until size()) {
+ action(keyAt(index), valueAt(index))
+ }
+}
+
+/** Return an iterator over the collection's keys. */
+fun <T> SparseArrayCompat<T>.keyIterator(): IntIterator = object : IntIterator() {
+ var index = 0
+ override fun hasNext() = index < size()
+ override fun nextInt() = keyAt(index++)
+}
+
+/** Return an iterator over the collection's values. */
+fun <T> SparseArrayCompat<T>.valueIterator(): Iterator<T> = object : Iterator<T> {
+ var index = 0
+ override fun hasNext() = index < size()
+ override fun next() = valueAt(index++)
+}
diff --git a/collection-ktx/src/test/java/androidx/collection/ArrayMapTest.kt b/collection-ktx/src/test/java/androidx/collection/ArrayMapTest.kt
new file mode 100644
index 0000000..8c002dd
--- /dev/null
+++ b/collection-ktx/src/test/java/androidx/collection/ArrayMapTest.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2017 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.collection
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class ArrayMapTest {
+ @Test fun empty() {
+ val map = arrayMapOf<String, String>()
+ assertEquals(0, map.size)
+ }
+
+ @Test fun nonEmpty() {
+ val map = arrayMapOf("foo" to "bar", "bar" to "baz")
+ assertThat(map).containsExactly("foo", "bar", "bar", "baz")
+ }
+
+ @Test fun duplicateKeyKeepsLast() {
+ val map = arrayMapOf("foo" to "bar", "foo" to "baz")
+ assertThat(map).containsExactly("foo", "baz")
+ }
+}
diff --git a/collection-ktx/src/test/java/androidx/collection/ArraySetTest.kt b/collection-ktx/src/test/java/androidx/collection/ArraySetTest.kt
new file mode 100644
index 0000000..71a561d
--- /dev/null
+++ b/collection-ktx/src/test/java/androidx/collection/ArraySetTest.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 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.collection
+
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class ArraySetTest {
+ @Test fun empty() {
+ val set = arraySetOf<String>()
+ assertEquals(0, set.size)
+ }
+
+ @Test fun nonEmpty() {
+ val set = arraySetOf("foo", "bar", "baz")
+ assertThat(set).containsExactly("foo", "bar", "baz")
+ }
+}
diff --git a/collection-ktx/src/test/java/androidx/collection/LongSparseArrayTest.kt b/collection-ktx/src/test/java/androidx/collection/LongSparseArrayTest.kt
new file mode 100644
index 0000000..3419664
--- /dev/null
+++ b/collection-ktx/src/test/java/androidx/collection/LongSparseArrayTest.kt
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2017 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.collection
+
+import androidx.testutils.fail
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertSame
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class LongSparseArrayTest {
+ @Test fun sizeProperty() {
+ val array = LongSparseArray<String>()
+ assertEquals(0, array.size)
+ array.put(1L, "one")
+ assertEquals(1, array.size)
+ }
+
+ @Test fun containsOperator() {
+ val array = LongSparseArray<String>()
+ assertFalse(1L in array)
+ array.put(1L, "one")
+ assertTrue(1L in array)
+ }
+
+ @Test fun containsOperatorWithValue() {
+ val array = LongSparseArray<String>()
+
+ array.put(1L, "one")
+ assertFalse(2L in array)
+
+ array.put(2L, "two")
+ assertTrue(2L in array)
+ }
+
+ @Test fun setOperator() {
+ val array = LongSparseArray<String>()
+ array[1L] = "one"
+ assertEquals("one", array.get(1L))
+ }
+
+ @Test fun plusOperator() {
+ val first = LongSparseArray<String>().apply { put(1L, "one") }
+ val second = LongSparseArray<String>().apply { put(2L, "two") }
+ val combined = first + second
+ assertEquals(2, combined.size())
+ assertEquals(1L, combined.keyAt(0))
+ assertEquals("one", combined.valueAt(0))
+ assertEquals(2L, combined.keyAt(1))
+ assertEquals("two", combined.valueAt(1))
+ }
+
+ @Test fun containsKey() {
+ val array = LongSparseArray<String>()
+ assertFalse(array.containsKey(1L))
+ array.put(1L, "one")
+ assertTrue(array.containsKey(1L))
+ }
+
+ @Test fun containsKeyWithValue() {
+ val array = LongSparseArray<String>()
+
+ array.put(1L, "one")
+ assertFalse(array.containsKey(2L))
+
+ array.put(2L, "one")
+ assertTrue(array.containsKey(2L))
+ }
+
+ @Test fun containsValue() {
+ val array = LongSparseArray<String>()
+ assertFalse(array.containsValue("one"))
+ array.put(1L, "one")
+ assertTrue(array.containsValue("one"))
+ }
+
+ @Test fun getOrDefault() {
+ val array = LongSparseArray<Any>()
+ val default = Any()
+ assertSame(default, array.getOrDefault(1L, default))
+ array.put(1L, "one")
+ assertEquals("one", array.getOrDefault(1L, default))
+ }
+
+ @Test fun getOrElse() {
+ val array = LongSparseArray<Any>()
+ val default = Any()
+ assertSame(default, array.getOrElse(1L) { default })
+ array.put(1L, "one")
+ assertEquals("one", array.getOrElse(1L) { fail() })
+ }
+
+ @Test fun isNotEmpty() {
+ val array = LongSparseArray<String>()
+ assertFalse(array.isNotEmpty())
+ array.put(1L, "one")
+ assertTrue(array.isNotEmpty())
+ }
+
+ @Test fun removeValue() {
+ val array = LongSparseArray<String>()
+ array.put(1L, "one")
+ assertFalse(array.remove(0L, "one"))
+ assertEquals(1, array.size())
+ assertFalse(array.remove(1L, "two"))
+ assertEquals(1, array.size())
+ assertTrue(array.remove(1L, "one"))
+ assertEquals(0, array.size())
+ }
+
+ @Test fun putAll() {
+ val dest = LongSparseArray<String>()
+ val source = LongSparseArray<String>()
+ source.put(1L, "one")
+
+ assertEquals(0, dest.size())
+ dest.putAll(source)
+ assertEquals(1, dest.size())
+ }
+
+ @Test fun forEach() {
+ val array = LongSparseArray<String>()
+ array.forEach { _, _ -> fail() }
+
+ array.put(1L, "one")
+ array.put(2L, "two")
+ array.put(6L, "six")
+
+ val keys = mutableListOf<Long>()
+ val values = mutableListOf<String>()
+ array.forEach { key, value ->
+ keys.add(key)
+ values.add(value)
+ }
+ assertThat(keys).containsExactly(1L, 2L, 6L)
+ assertThat(values).containsExactly("one", "two", "six")
+ }
+
+ @Test fun keyIterator() {
+ val array = LongSparseArray<String>()
+ assertFalse(array.keyIterator().hasNext())
+
+ array.put(1L, "one")
+ array.put(2L, "two")
+ array.put(6L, "six")
+
+ val iterator = array.keyIterator()
+ assertTrue(iterator.hasNext())
+ assertEquals(1L, iterator.nextLong())
+ assertTrue(iterator.hasNext())
+ assertEquals(2L, iterator.nextLong())
+ assertTrue(iterator.hasNext())
+ assertEquals(6L, iterator.nextLong())
+ assertFalse(iterator.hasNext())
+ }
+
+ @Test fun valueIterator() {
+ val array = LongSparseArray<String>()
+ assertFalse(array.valueIterator().hasNext())
+
+ array.put(1L, "one")
+ array.put(2L, "two")
+ array.put(6L, "six")
+
+ val iterator = array.valueIterator()
+ assertTrue(iterator.hasNext())
+ assertEquals("one", iterator.next())
+ assertTrue(iterator.hasNext())
+ assertEquals("two", iterator.next())
+ assertTrue(iterator.hasNext())
+ assertEquals("six", iterator.next())
+ assertFalse(iterator.hasNext())
+ }
+}
diff --git a/collection-ktx/src/test/java/androidx/collection/LruCacheTest.kt b/collection-ktx/src/test/java/androidx/collection/LruCacheTest.kt
new file mode 100644
index 0000000..c47b423
--- /dev/null
+++ b/collection-ktx/src/test/java/androidx/collection/LruCacheTest.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 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.collection
+
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class LruCacheTest {
+ private data class TestData(val x: String = "bla")
+
+ @Test fun size() {
+ val cache = lruCache<String, TestData>(200, { k, (x) -> k.length * x.length })
+ cache.put("long", TestData())
+ assertEquals(cache.size(), 12)
+ }
+
+ @Test fun create() {
+ val cache = lruCache<String, TestData>(200, create = { key -> TestData("$key foo") })
+ assertEquals(cache.get("kung"), TestData("kung foo"))
+ }
+
+ @Test fun onEntryRemoved() {
+ var wasCalled = false
+
+ val cache = lruCache<String, TestData>(200, onEntryRemoved = { _, _, _, _ ->
+ wasCalled = true
+ })
+ val initial = TestData()
+ cache.put("a", initial)
+ cache.remove("a")
+ assertTrue(wasCalled)
+ }
+}
diff --git a/collection-ktx/src/test/java/androidx/collection/SparseArrayTest.kt b/collection-ktx/src/test/java/androidx/collection/SparseArrayTest.kt
new file mode 100644
index 0000000..90d46c8
--- /dev/null
+++ b/collection-ktx/src/test/java/androidx/collection/SparseArrayTest.kt
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2017 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.collection
+
+import androidx.testutils.fail
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertSame
+import org.junit.Assert.assertTrue
+import org.junit.Test
+
+class SparseArrayCompatTest {
+ @Test fun sizeProperty() {
+ val array = SparseArrayCompat<String>()
+ assertEquals(0, array.size)
+ array.put(1, "one")
+ assertEquals(1, array.size)
+ }
+
+ @Test fun containsOperator() {
+ val array = SparseArrayCompat<String>()
+ assertFalse(1 in array)
+ array.put(1, "one")
+ assertTrue(1 in array)
+ }
+
+ @Test fun containsOperatorWithItem() {
+ val array = SparseArrayCompat<String>()
+
+ array.put(1, "one")
+ assertFalse(2 in array)
+
+ array.put(2, "two")
+ assertTrue(2 in array)
+ }
+
+ @Test fun setOperator() {
+ val array = SparseArrayCompat<String>()
+ array[1] = "one"
+ assertEquals("one", array.get(1))
+ }
+
+ @Test fun plusOperator() {
+ val first = SparseArrayCompat<String>().apply { put(1, "one") }
+ val second = SparseArrayCompat<String>().apply { put(2, "two") }
+ val combined = first + second
+ assertEquals(2, combined.size())
+ assertEquals(1, combined.keyAt(0))
+ assertEquals("one", combined.valueAt(0))
+ assertEquals(2, combined.keyAt(1))
+ assertEquals("two", combined.valueAt(1))
+ }
+
+ @Test fun containsKey() {
+ val array = SparseArrayCompat<String>()
+ assertFalse(array.containsKey(1))
+ array.put(1, "one")
+ assertTrue(array.containsKey(1))
+ }
+
+ @Test fun containsValue() {
+ val array = SparseArrayCompat<String>()
+ assertFalse(array.containsValue("one"))
+ array.put(1, "one")
+ assertTrue(array.containsValue("one"))
+ }
+
+ @Test fun getOrDefault() {
+ val array = SparseArrayCompat<Any>()
+ val default = Any()
+ assertSame(default, array.getOrDefault(1, default))
+ array.put(1, "one")
+ assertEquals("one", array.getOrDefault(1, default))
+ }
+
+ @Test fun getOrElse() {
+ val array = SparseArrayCompat<Any>()
+ val default = Any()
+ assertSame(default, array.getOrElse(1) { default })
+ array.put(1, "one")
+ assertEquals("one", array.getOrElse(1) { fail() })
+ }
+
+ @Test fun isNotEmpty() {
+ val array = SparseArrayCompat<String>()
+ assertFalse(array.isNotEmpty())
+ array.put(1, "one")
+ assertTrue(array.isNotEmpty())
+ }
+
+ @Test fun removeValue() {
+ val array = SparseArrayCompat<String>()
+ array.put(1, "one")
+ assertFalse(array.remove(0, "one"))
+ assertEquals(1, array.size())
+ assertFalse(array.remove(1, "two"))
+ assertEquals(1, array.size())
+ assertTrue(array.remove(1, "one"))
+ assertEquals(0, array.size())
+ }
+
+ @Test fun putAll() {
+ val dest = SparseArrayCompat<String>()
+ val source = SparseArrayCompat<String>()
+ source.put(1, "one")
+
+ assertEquals(0, dest.size())
+ dest.putAll(source)
+ assertEquals(1, dest.size())
+ }
+
+ @Test fun forEach() {
+ val array = SparseArrayCompat<String>()
+ array.forEach { _, _ -> fail() }
+
+ array.put(1, "one")
+ array.put(2, "two")
+ array.put(6, "six")
+
+ val keys = mutableListOf<Int>()
+ val values = mutableListOf<String>()
+ array.forEach { key, value ->
+ keys.add(key)
+ values.add(value)
+ }
+ assertThat(keys).containsExactly(1, 2, 6)
+ assertThat(values).containsExactly("one", "two", "six")
+ }
+
+ @Test fun keyIterator() {
+ val array = SparseArrayCompat<String>()
+ assertFalse(array.keyIterator().hasNext())
+
+ array.put(1, "one")
+ array.put(2, "two")
+ array.put(6, "six")
+
+ val iterator = array.keyIterator()
+ assertTrue(iterator.hasNext())
+ assertEquals(1, iterator.nextInt())
+ assertTrue(iterator.hasNext())
+ assertEquals(2, iterator.nextInt())
+ assertTrue(iterator.hasNext())
+ assertEquals(6, iterator.nextInt())
+ assertFalse(iterator.hasNext())
+ }
+
+ @Test fun valueIterator() {
+ val array = SparseArrayCompat<String>()
+ assertFalse(array.valueIterator().hasNext())
+
+ array.put(1, "one")
+ array.put(2, "two")
+ array.put(6, "six")
+
+ val iterator = array.valueIterator()
+ assertTrue(iterator.hasNext())
+ assertEquals("one", iterator.next())
+ assertTrue(iterator.hasNext())
+ assertEquals("two", iterator.next())
+ assertTrue(iterator.hasNext())
+ assertEquals("six", iterator.next())
+ assertFalse(iterator.hasNext())
+ }
+}
diff --git a/palette-ktx/OWNERS b/palette-ktx/OWNERS
new file mode 100644
index 0000000..e450f4c
--- /dev/null
+++ b/palette-ktx/OWNERS
@@ -0,0 +1 @@
+jakew@google.com
diff --git a/palette-ktx/build.gradle b/palette-ktx/build.gradle
new file mode 100644
index 0000000..f5946aa
--- /dev/null
+++ b/palette-ktx/build.gradle
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 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 static androidx.build.dependencies.DependenciesKt.*
+import androidx.build.LibraryGroups
+import androidx.build.LibraryVersions
+
+plugins {
+ id("SupportAndroidLibraryPlugin")
+ id("org.jetbrains.kotlin.android")
+}
+
+android {
+ buildTypes {
+ debug {
+ testCoverageEnabled = false // Breaks Kotlin compiler.
+ }
+ }
+}
+
+dependencies {
+ api(project(":palette"))
+ api(KOTLIN_STDLIB)
+ androidTestImplementation(JUNIT)
+ androidTestImplementation(TEST_RUNNER_TMP, libs.exclude_for_espresso)
+}
+
+supportLibrary {
+ name = "Palette Kotlin Extensions"
+ publish = true
+ mavenVersion = LibraryVersions.SUPPORT_LIBRARY
+ mavenGroup = LibraryGroups.FRAGMENT
+ inceptionYear = "2018"
+ description = "Kotlin extensions for 'palette' artifact"
+}
diff --git a/palette-ktx/src/androidTest/java/androidx/palette/graphics/PaletteTest.kt b/palette-ktx/src/androidTest/java/androidx/palette/graphics/PaletteTest.kt
new file mode 100644
index 0000000..c108493
--- /dev/null
+++ b/palette-ktx/src/androidTest/java/androidx/palette/graphics/PaletteTest.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018 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.palette.graphics
+
+import android.graphics.Bitmap
+import android.graphics.Bitmap.Config.ARGB_8888
+import android.graphics.Canvas
+import android.graphics.Color.RED
+import androidx.palette.graphics.Target.VIBRANT
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertSame
+import org.junit.Test
+
+class PaletteTest {
+ @Test fun bitmapBuild() {
+ val bitmap = Bitmap.createBitmap(10, 10, ARGB_8888)
+ // There's no easy way to test that the palette was created from our Bitmap.
+ assertNotNull(bitmap.buildPalette())
+ }
+
+ @Test fun operatorGet() {
+ val bitmap = Bitmap.createBitmap(10, 10, ARGB_8888).apply {
+ Canvas(this).drawColor(RED)
+ }
+ val palette = Palette.from(bitmap).generate()
+ assertSame(palette.getSwatchForTarget(VIBRANT), palette[VIBRANT])
+ }
+}
diff --git a/palette-ktx/src/main/AndroidManifest.xml b/palette-ktx/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f25fda5
--- /dev/null
+++ b/palette-ktx/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 2018 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 package="androidx.palette.ktx"/>
diff --git a/palette-ktx/src/main/java/androidx/palette/graphics/Palette.kt b/palette-ktx/src/main/java/androidx/palette/graphics/Palette.kt
new file mode 100644
index 0000000..58da09a
--- /dev/null
+++ b/palette-ktx/src/main/java/androidx/palette/graphics/Palette.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2018 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.
+ */
+
+@file:Suppress("NOTHING_TO_INLINE") // Aliases to public API.
+
+package androidx.palette.graphics
+
+import android.graphics.Bitmap
+
+/**
+ * Create a [Palette.Builder] from this bitmap.
+ *
+ * @see Palette.from
+ */
+inline fun Bitmap.buildPalette() = Palette.Builder(this)
+
+/**
+ * Returns the selected swatch for the given target from the palette, or `null` if one
+ * could not be found.
+ *
+ * @see Palette.getSwatchForTarget
+ */
+inline operator fun Palette.get(target: Target): Palette.Swatch? = getSwatchForTarget(target)
diff --git a/settings.gradle b/settings.gradle
index c402bf3..2642a19 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -39,6 +39,7 @@
includeProject(":car", "car")
includeProject(":cardview", "cardview")
includeProject(":collection", "collection")
+includeProject(":collection-ktx", "collection-ktx")
includeProject(":coordinatorlayout", "coordinatorlayout")
includeProject(":cursoradapter", "cursoradapter")
includeProject(":browser", "browser")
@@ -58,6 +59,7 @@
includeProject(":localbroadcastmanager", "localbroadcastmanager")
includeProject(":mediarouter", "mediarouter")
includeProject(":palette", "palette")
+includeProject(":palette-ktx", "palette-ktx")
includeProject(":percentlayout", "percent")
includeProject(":preference", "preference")
includeProject(":leanback-preference", "leanback-preference")
@@ -135,6 +137,7 @@
/////////////////////////////
includeProject(":internal-testutils", "testutils")
+includeProject(":internal-testutils-ktx", "testutils-ktx")
/////////////////////////////
//
diff --git a/slices/view/src/androidTest/java/androidx/slice/SliceManagerTest.java b/slices/view/src/androidTest/java/androidx/slice/SliceManagerTest.java
index 52e6ef6..2e5ed54 100644
--- a/slices/view/src/androidTest/java/androidx/slice/SliceManagerTest.java
+++ b/slices/view/src/androidTest/java/androidx/slice/SliceManagerTest.java
@@ -42,6 +42,7 @@
import java.util.concurrent.Executor;
+import androidx.slice.render.SliceRenderActivity;
import androidx.slice.widget.SliceLiveData;
@RunWith(AndroidJUnit4.class)
@@ -124,14 +125,14 @@
assertEquals(SliceLiveData.SUPPORTED_SPECS, mManager.getPinnedSpecs(uri));
}
- //@Test
- //public void testMapIntentToUri() {
- // Uri expected = Uri.parse("content://androidx.slice.view.test/render");
- // Slice s = new Slice.Builder(expected).build();
- // when(mSliceProvider.onBindSlice(eq(expected))).thenReturn(s);
- // Uri uri = mManager.mapIntentToUri(new Intent(mContext, SliceRenderActivity.class));
- // assertEquals(expected, uri);
- //}
+ @Test
+ public void testMapIntentToUri() {
+ Uri expected = Uri.parse("content://androidx.slice.view.test/render");
+ Slice s = new Slice.Builder(expected).build();
+ when(mSliceProvider.onBindSlice(eq(expected))).thenReturn(s);
+ Uri uri = mManager.mapIntentToUri(new Intent(mContext, SliceRenderActivity.class));
+ assertEquals(expected, uri);
+ }
public static class TestSliceProvider extends SliceProvider {
diff --git a/slices/view/src/main/java/androidx/slice/SliceManagerWrapper.java b/slices/view/src/main/java/androidx/slice/SliceManagerWrapper.java
index 6b857f4..1169547 100644
--- a/slices/view/src/main/java/androidx/slice/SliceManagerWrapper.java
+++ b/slices/view/src/main/java/androidx/slice/SliceManagerWrapper.java
@@ -19,7 +19,6 @@
import static androidx.slice.SliceConvert.unwrap;
import static androidx.slice.widget.SliceLiveData.SUPPORTED_SPECS;
-import android.app.slice.SliceManager;
import android.app.slice.SliceSpec;
import android.content.Context;
import android.content.Intent;
@@ -40,12 +39,6 @@
private final android.app.slice.SliceManager mManager;
private final List<SliceSpec> mSpecs;
- private final SliceManager.SliceCallback mCallback = new SliceManager.SliceCallback() {
- @Override
- public void onSliceUpdated(@NonNull android.app.slice.Slice s) {
-
- }
- };
SliceManagerWrapper(Context context) {
this(context, context.getSystemService(android.app.slice.SliceManager.class));
@@ -59,12 +52,12 @@
@Override
public void pinSlice(@NonNull Uri uri) {
- mManager.registerSliceCallback(uri, mSpecs, mCallback);
+ mManager.pinSlice(uri, mSpecs);
}
@Override
public void unpinSlice(@NonNull Uri uri) {
- mManager.unregisterSliceCallback(uri, mCallback);
+ mManager.unpinSlice(uri);
}
@Override
diff --git a/testutils-ktx/NO_DOCS b/testutils-ktx/NO_DOCS
new file mode 100644
index 0000000..4dad694
--- /dev/null
+++ b/testutils-ktx/NO_DOCS
@@ -0,0 +1,17 @@
+# Copyright (C) 2017 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.
+
+Having this file, named NO_DOCS, in a directory will prevent
+Android javadocs from being generated for java files under
+the directory. This is especially useful for test projects.
diff --git a/testutils-ktx/OWNERS b/testutils-ktx/OWNERS
new file mode 100644
index 0000000..e450f4c
--- /dev/null
+++ b/testutils-ktx/OWNERS
@@ -0,0 +1 @@
+jakew@google.com
diff --git a/testutils-ktx/build.gradle b/testutils-ktx/build.gradle
new file mode 100644
index 0000000..5f33da1
--- /dev/null
+++ b/testutils-ktx/build.gradle
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018 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 static androidx.build.dependencies.DependenciesKt.*
+
+plugins {
+ id("SupportKotlinLibraryPlugin")
+}
+
+dependencies {
+ compile(KOTLIN_STDLIB)
+ compile(TRUTH)
+}
diff --git a/testutils-ktx/src/main/java/androidx/testutils/assertions.kt b/testutils-ktx/src/main/java/androidx/testutils/assertions.kt
new file mode 100644
index 0000000..b67948a
--- /dev/null
+++ b/testutils-ktx/src/main/java/androidx/testutils/assertions.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2018 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.testutils
+
+import com.google.common.truth.ThrowableSubject
+import com.google.common.truth.Truth.assertThat
+
+inline fun <reified T : Throwable> assertThrows(body: () -> Unit): ThrowableSubject {
+ try {
+ body()
+ } catch (e: Throwable) {
+ if (e is T) {
+ return assertThat(e)
+ }
+ throw e
+ }
+ throw AssertionError("Body completed successfully. Expected ${T::class.java.simpleName}.")
+}
+
+fun fail(message: String? = null): Nothing = throw AssertionError(message)
diff --git a/webkit/api/current.txt b/webkit/api/current.txt
new file mode 100644
index 0000000..2a39d42
--- /dev/null
+++ b/webkit/api/current.txt
@@ -0,0 +1,24 @@
+package androidx.webkit {
+
+ public class WebSettingsCompat {
+ method public static int getDisabledActionModeMenuItems(android.webkit.WebSettings);
+ method public static boolean getOffscreenPreRaster(android.webkit.WebSettings);
+ method public static boolean getSafeBrowsingEnabled(android.webkit.WebSettings);
+ method public static void setDisabledActionModeMenuItems(android.webkit.WebSettings, int);
+ method public static void setOffscreenPreRaster(android.webkit.WebSettings, boolean);
+ method public static void setSafeBrowsingEnabled(android.webkit.WebSettings, boolean);
+ }
+
+ public class WebViewCompat {
+ method public static android.net.Uri getSafeBrowsingPrivacyPolicyUrl();
+ method public static void postVisualStateCallback(android.webkit.WebView, long, androidx.webkit.WebViewCompat.VisualStateCallback);
+ method public static void setSafeBrowsingWhitelist(java.util.List<java.lang.String>, android.webkit.ValueCallback<java.lang.Boolean>);
+ method public static void startSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean>);
+ }
+
+ public static abstract interface WebViewCompat.VisualStateCallback {
+ method public abstract void onComplete(long);
+ }
+
+}
+
diff --git a/webkit/build.gradle b/webkit/build.gradle
index 06f3801..9b2b5d3 100644
--- a/webkit/build.gradle
+++ b/webkit/build.gradle
@@ -38,11 +38,15 @@
// Allow compiling the WebView support library boundary interfaces from this project.
main.java.srcDirs += new File(webviewBoundaryInterfacesDir, "src").getAbsolutePath()
}
+
+ buildTypes.all {
+ consumerProguardFiles new File(webviewBoundaryInterfacesDir, "proguard.flags")
+ }
}
supportLibrary {
name = "WebView Support Library"
- publish = false
+ publish = true
mavenVersion = LibraryVersions.SUPPORT_LIBRARY
mavenGroup = LibraryGroups.WEBKIT
inceptionYear = "2017"
diff --git a/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java b/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
index c73cda6..12d7e63 100644
--- a/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
+++ b/webkit/src/main/java/androidx/webkit/WebSettingsCompat.java
@@ -19,6 +19,13 @@
import android.os.Build;
import android.webkit.WebSettings;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.RestrictTo;
import androidx.webkit.internal.WebSettingsAdapter;
import androidx.webkit.internal.WebViewGlueCommunicator;
@@ -102,10 +109,25 @@
}
/**
+ * @hide
+ */
+ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+ @IntDef(flag = true, value = {
+ WebSettings.MENU_ITEM_NONE,
+ WebSettings.MENU_ITEM_SHARE,
+ WebSettings.MENU_ITEM_WEB_SEARCH,
+ WebSettings.MENU_ITEM_PROCESS_TEXT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @Target({ElementType.PARAMETER, ElementType.METHOD})
+ public @interface MenuItemFlags {}
+
+ /**
* Disables the action mode menu items according to {@code menuItems} flag.
* @param menuItems an integer field flag for the menu items to be disabled.
*/
- public static void setDisabledActionModeMenuItems(WebSettings webSettings, int menuItems) {
+ public static void setDisabledActionModeMenuItems(WebSettings webSettings,
+ @MenuItemFlags int menuItems) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
webSettings.setDisabledActionModeMenuItems(menuItems);
} else {
@@ -119,7 +141,7 @@
*
* @return all the disabled menu item flags combined with bitwise OR.
*/
- public static int getDisabledActionModeMenuItems(WebSettings webSettings) {
+ public static @MenuItemFlags int getDisabledActionModeMenuItems(WebSettings webSettings) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return webSettings.getDisabledActionModeMenuItems();
} else {