Merge "Revert WM changes from "Add concurrent:concurrent-futures-ktx"" into androidx-master-dev
diff --git a/work/workmanager-ktx/api/2.3.0-alpha02.ignore b/work/workmanager-ktx/api/2.3.0-alpha02.ignore
deleted file mode 100644
index 8aff62a..0000000
--- a/work/workmanager-ktx/api/2.3.0-alpha02.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-RemovedClass: androidx.work.ListenableFutureKt:
-    Removed class androidx.work.ListenableFutureKt
diff --git a/work/workmanager-ktx/api/2.3.0-alpha02.txt b/work/workmanager-ktx/api/2.3.0-alpha02.txt
index b875ebc..5873b39 100644
--- a/work/workmanager-ktx/api/2.3.0-alpha02.txt
+++ b/work/workmanager-ktx/api/2.3.0-alpha02.txt
@@ -18,6 +18,10 @@
     method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
   }
 
+  public final class ListenableFutureKt {
+    ctor public ListenableFutureKt();
+  }
+
   public final class OneTimeWorkRequestKt {
     ctor public OneTimeWorkRequestKt();
     method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder OneTimeWorkRequestBuilder();
diff --git a/work/workmanager-ktx/api/2.3.0-alpha04.ignore b/work/workmanager-ktx/api/2.3.0-alpha04.ignore
deleted file mode 100644
index 8aff62a..0000000
--- a/work/workmanager-ktx/api/2.3.0-alpha04.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-RemovedClass: androidx.work.ListenableFutureKt:
-    Removed class androidx.work.ListenableFutureKt
diff --git a/work/workmanager-ktx/api/2.3.0-alpha04.txt b/work/workmanager-ktx/api/2.3.0-alpha04.txt
index b875ebc..5873b39 100644
--- a/work/workmanager-ktx/api/2.3.0-alpha04.txt
+++ b/work/workmanager-ktx/api/2.3.0-alpha04.txt
@@ -18,6 +18,10 @@
     method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
   }
 
+  public final class ListenableFutureKt {
+    ctor public ListenableFutureKt();
+  }
+
   public final class OneTimeWorkRequestKt {
     ctor public OneTimeWorkRequestKt();
     method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder OneTimeWorkRequestBuilder();
diff --git a/work/workmanager-ktx/api/current.txt b/work/workmanager-ktx/api/current.txt
index b875ebc..5873b39 100644
--- a/work/workmanager-ktx/api/current.txt
+++ b/work/workmanager-ktx/api/current.txt
@@ -18,6 +18,10 @@
     method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
   }
 
+  public final class ListenableFutureKt {
+    ctor public ListenableFutureKt();
+  }
+
   public final class OneTimeWorkRequestKt {
     ctor public OneTimeWorkRequestKt();
     method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder OneTimeWorkRequestBuilder();
diff --git a/work/workmanager-ktx/api/public_plus_experimental_2.3.0-alpha02.txt b/work/workmanager-ktx/api/public_plus_experimental_2.3.0-alpha02.txt
index b875ebc..5873b39 100644
--- a/work/workmanager-ktx/api/public_plus_experimental_2.3.0-alpha02.txt
+++ b/work/workmanager-ktx/api/public_plus_experimental_2.3.0-alpha02.txt
@@ -18,6 +18,10 @@
     method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
   }
 
+  public final class ListenableFutureKt {
+    ctor public ListenableFutureKt();
+  }
+
   public final class OneTimeWorkRequestKt {
     ctor public OneTimeWorkRequestKt();
     method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder OneTimeWorkRequestBuilder();
diff --git a/work/workmanager-ktx/api/public_plus_experimental_2.3.0-alpha04.txt b/work/workmanager-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
index b875ebc..5873b39 100644
--- a/work/workmanager-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
+++ b/work/workmanager-ktx/api/public_plus_experimental_2.3.0-alpha04.txt
@@ -18,6 +18,10 @@
     method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
   }
 
+  public final class ListenableFutureKt {
+    ctor public ListenableFutureKt();
+  }
+
   public final class OneTimeWorkRequestKt {
     ctor public OneTimeWorkRequestKt();
     method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder OneTimeWorkRequestBuilder();
diff --git a/work/workmanager-ktx/api/public_plus_experimental_current.txt b/work/workmanager-ktx/api/public_plus_experimental_current.txt
index b875ebc..5873b39 100644
--- a/work/workmanager-ktx/api/public_plus_experimental_current.txt
+++ b/work/workmanager-ktx/api/public_plus_experimental_current.txt
@@ -18,6 +18,10 @@
     method public static inline androidx.work.Data workDataOf(kotlin.Pair<java.lang.String,?>... pairs);
   }
 
+  public final class ListenableFutureKt {
+    ctor public ListenableFutureKt();
+  }
+
   public final class OneTimeWorkRequestKt {
     ctor public OneTimeWorkRequestKt();
     method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder OneTimeWorkRequestBuilder();
diff --git a/work/workmanager-ktx/api/restricted_2.3.0-alpha02.ignore b/work/workmanager-ktx/api/restricted_2.3.0-alpha02.ignore
deleted file mode 100644
index 8aff62a..0000000
--- a/work/workmanager-ktx/api/restricted_2.3.0-alpha02.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-RemovedClass: androidx.work.ListenableFutureKt:
-    Removed class androidx.work.ListenableFutureKt
diff --git a/work/workmanager-ktx/api/restricted_2.3.0-alpha02.txt b/work/workmanager-ktx/api/restricted_2.3.0-alpha02.txt
index 1cff0b6..075851a 100644
--- a/work/workmanager-ktx/api/restricted_2.3.0-alpha02.txt
+++ b/work/workmanager-ktx/api/restricted_2.3.0-alpha02.txt
@@ -23,6 +23,11 @@
     enum_constant public static final androidx.work.DirectExecutor INSTANCE;
   }
 
+  public final class ListenableFutureKt {
+    ctor public ListenableFutureKt();
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static suspend inline <R> Object! await(com.google.common.util.concurrent.ListenableFuture<R>, kotlin.coroutines.Continuation<? super R> p);
+  }
+
   public final class OneTimeWorkRequestKt {
     ctor public OneTimeWorkRequestKt();
     method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder OneTimeWorkRequestBuilder();
diff --git a/work/workmanager-ktx/api/restricted_2.3.0-alpha04.ignore b/work/workmanager-ktx/api/restricted_2.3.0-alpha04.ignore
deleted file mode 100644
index 8aff62a..0000000
--- a/work/workmanager-ktx/api/restricted_2.3.0-alpha04.ignore
+++ /dev/null
@@ -1,3 +0,0 @@
-// Baseline format: 1.0
-RemovedClass: androidx.work.ListenableFutureKt:
-    Removed class androidx.work.ListenableFutureKt
diff --git a/work/workmanager-ktx/api/restricted_2.3.0-alpha04.txt b/work/workmanager-ktx/api/restricted_2.3.0-alpha04.txt
index 1cff0b6..075851a 100644
--- a/work/workmanager-ktx/api/restricted_2.3.0-alpha04.txt
+++ b/work/workmanager-ktx/api/restricted_2.3.0-alpha04.txt
@@ -23,6 +23,11 @@
     enum_constant public static final androidx.work.DirectExecutor INSTANCE;
   }
 
+  public final class ListenableFutureKt {
+    ctor public ListenableFutureKt();
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static suspend inline <R> Object! await(com.google.common.util.concurrent.ListenableFuture<R>, kotlin.coroutines.Continuation<? super R> p);
+  }
+
   public final class OneTimeWorkRequestKt {
     ctor public OneTimeWorkRequestKt();
     method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder OneTimeWorkRequestBuilder();
diff --git a/work/workmanager-ktx/api/restricted_current.txt b/work/workmanager-ktx/api/restricted_current.txt
index 1cff0b6..075851a 100644
--- a/work/workmanager-ktx/api/restricted_current.txt
+++ b/work/workmanager-ktx/api/restricted_current.txt
@@ -23,6 +23,11 @@
     enum_constant public static final androidx.work.DirectExecutor INSTANCE;
   }
 
+  public final class ListenableFutureKt {
+    ctor public ListenableFutureKt();
+    method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static suspend inline <R> Object! await(com.google.common.util.concurrent.ListenableFuture<R>, kotlin.coroutines.Continuation<? super R> p);
+  }
+
   public final class OneTimeWorkRequestKt {
     ctor public OneTimeWorkRequestKt();
     method public static inline <reified W extends androidx.work.ListenableWorker> androidx.work.OneTimeWorkRequest.Builder OneTimeWorkRequestBuilder();
diff --git a/work/workmanager-ktx/build.gradle b/work/workmanager-ktx/build.gradle
index 6b74ce6..2a279bb 100644
--- a/work/workmanager-ktx/build.gradle
+++ b/work/workmanager-ktx/build.gradle
@@ -45,8 +45,8 @@
     api project(':work:work-runtime')
     api(KOTLIN_STDLIB)
     api(KOTLIN_COROUTINES_ANDROID)
-    implementation project(':concurrent:concurrent-futures-ktx')
 
+    androidTestImplementation("androidx.concurrent:concurrent-futures:1.0.0")
     androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
     androidTestImplementation(ANDROIDX_TEST_CORE)
     androidTestImplementation(ANDROIDX_TEST_RUNNER)
diff --git a/work/workmanager-ktx/src/androidTest/java/androidx/work/ListenableFutureTest.kt b/work/workmanager-ktx/src/androidTest/java/androidx/work/ListenableFutureTest.kt
new file mode 100644
index 0000000..1f87734
--- /dev/null
+++ b/work/workmanager-ktx/src/androidTest/java/androidx/work/ListenableFutureTest.kt
@@ -0,0 +1,75 @@
+/*
+ * 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.work
+
+import androidx.concurrent.futures.ResolvableFuture
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import org.hamcrest.CoreMatchers.`is`
+import org.hamcrest.CoreMatchers.instanceOf
+import org.hamcrest.MatcherAssert.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class ListenableFutureTest {
+    @Test
+    fun testFutureWithResult() {
+        val future: ResolvableFuture<Int> = ResolvableFuture.create()
+        val job = GlobalScope.launch {
+            val result = future.await()
+            assertThat(result, `is`(10))
+        }
+        future.set(10)
+        runBlocking {
+            job.join()
+        }
+    }
+    @Test
+    fun testFutureWithException() {
+        val future: ResolvableFuture<Int> = ResolvableFuture.create()
+        val exception = RuntimeException("Something bad happened")
+        val job = GlobalScope.launch {
+            try {
+                future.await()
+            } catch (throwable: Throwable) {
+                assertThat(throwable, `is`(instanceOf(RuntimeException::class.java)))
+                assertThat(throwable.message, `is`(exception.message))
+            }
+        }
+        future.setException(exception)
+        runBlocking {
+            job.join()
+        }
+    }
+    @Test
+    fun testFutureCancellation() {
+        val future: ResolvableFuture<Int> = ResolvableFuture.create()
+        val job = GlobalScope.launch {
+            future.await()
+        }
+        future.cancel(true)
+        runBlocking {
+            job.join()
+            assertThat(job.isCancelled, `is`(true))
+        }
+    }
+}
diff --git a/work/workmanager-ktx/src/main/java/androidx/work/CoroutineWorker.kt b/work/workmanager-ktx/src/main/java/androidx/work/CoroutineWorker.kt
index e15192f..fa05791 100644
--- a/work/workmanager-ktx/src/main/java/androidx/work/CoroutineWorker.kt
+++ b/work/workmanager-ktx/src/main/java/androidx/work/CoroutineWorker.kt
@@ -17,7 +17,6 @@
 package androidx.work
 
 import android.content.Context
-import androidx.concurrent.futures.await
 import androidx.work.impl.utils.futures.SettableFuture
 import com.google.common.util.concurrent.ListenableFuture
 import kotlinx.coroutines.CoroutineScope
diff --git a/work/workmanager-ktx/src/main/java/androidx/work/ListenableFuture.kt b/work/workmanager-ktx/src/main/java/androidx/work/ListenableFuture.kt
new file mode 100644
index 0000000..51504ab
--- /dev/null
+++ b/work/workmanager-ktx/src/main/java/androidx/work/ListenableFuture.kt
@@ -0,0 +1,59 @@
+/*
+ * 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")
+
+package androidx.work
+
+import androidx.annotation.RestrictTo
+import com.google.common.util.concurrent.ListenableFuture
+import kotlinx.coroutines.suspendCancellableCoroutine
+import java.util.concurrent.CancellationException
+import java.util.concurrent.ExecutionException
+import kotlin.coroutines.resume
+import kotlin.coroutines.resumeWithException
+
+/**
+ * Awaits for the completion of the [ListenableFuture] without blocking a thread.
+ *
+ * @return R The result from the [ListenableFuture]
+ *
+ * @hide
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+suspend inline fun <R> ListenableFuture<R>.await(): R {
+    // Fast path
+    if (isDone) {
+        try {
+            return get()
+        } catch (e: ExecutionException) {
+            throw e.cause ?: e
+        }
+    }
+    return suspendCancellableCoroutine { cancellableContinuation ->
+        addListener(Runnable {
+            try {
+                cancellableContinuation.resume(get())
+            } catch (throwable: Throwable) {
+                val cause = throwable.cause ?: throwable
+                when (throwable) {
+                    is CancellationException -> cancellableContinuation.cancel(cause)
+                    else -> cancellableContinuation.resumeWithException(cause)
+                }
+            }
+        }, DirectExecutor.INSTANCE)
+    }
+}
diff --git a/work/workmanager-ktx/src/main/java/androidx/work/Operation.kt b/work/workmanager-ktx/src/main/java/androidx/work/Operation.kt
index 892cb51..c05181c 100644
--- a/work/workmanager-ktx/src/main/java/androidx/work/Operation.kt
+++ b/work/workmanager-ktx/src/main/java/androidx/work/Operation.kt
@@ -19,8 +19,6 @@
 
 package androidx.work
 
-import androidx.concurrent.futures.await
-
 /**
  * Awaits an [Operation] without blocking a thread.
  *
diff --git a/work/workmanager-testing/build.gradle b/work/workmanager-testing/build.gradle
index f7566fa..281b68b 100644
--- a/work/workmanager-testing/build.gradle
+++ b/work/workmanager-testing/build.gradle
@@ -40,7 +40,6 @@
     implementation("androidx.lifecycle:lifecycle-livedata-core:2.1.0")
     implementation("androidx.room:room-runtime:2.2.1")
 
-    androidTestImplementation(project(':concurrent:concurrent-futures-ktx'))
     androidTestImplementation("androidx.arch.core:core-testing:2.1.0")
     androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
     androidTestImplementation(ANDROIDX_TEST_CORE)
diff --git a/work/workmanager-testing/src/androidTest/java/androidx/work/testing/TestWorkerBuilderTest.kt b/work/workmanager-testing/src/androidTest/java/androidx/work/testing/TestWorkerBuilderTest.kt
index 51d9286..b9c085f 100644
--- a/work/workmanager-testing/src/androidTest/java/androidx/work/testing/TestWorkerBuilderTest.kt
+++ b/work/workmanager-testing/src/androidTest/java/androidx/work/testing/TestWorkerBuilderTest.kt
@@ -18,7 +18,6 @@
 
 import android.content.Context
 import android.net.Uri
-import androidx.concurrent.futures.await
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.MediumTest
@@ -27,6 +26,7 @@
 import androidx.work.OneTimeWorkRequestBuilder
 import androidx.work.WorkerFactory
 import androidx.work.WorkerParameters
+import androidx.work.await
 import androidx.work.testing.workers.TestListenableWorker
 import androidx.work.testing.workers.TestWorker
 import kotlinx.coroutines.runBlocking