[go: nahoru, domu]

Merge "RxJava3: RxJava wrapper around getForegroundInfoAsync" into androidx-main
diff --git a/work/work-rxjava2/src/test/java/androidx/work/RxForegroundInfoTest.kt b/work/work-rxjava2/src/test/java/androidx/work/RxForegroundInfoTest.kt
new file mode 100644
index 0000000..b901812
--- /dev/null
+++ b/work/work-rxjava2/src/test/java/androidx/work/RxForegroundInfoTest.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2021 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 android.content.Context
+import androidx.work.impl.utils.SynchronousExecutor
+import io.reactivex.Single
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mockito.mock
+import java.util.UUID
+import java.util.concurrent.Executor
+
+@RunWith(JUnit4::class)
+class SingleForegroundInfoTest {
+
+    @Test
+    fun foo() {
+        val context = mock(Context::class.java)
+        TestRxWorker(context, createWorkerParams())
+    }
+
+    private fun createWorkerParams(
+        executor: Executor = SynchronousExecutor(),
+        progressUpdater: ProgressUpdater = mock(ProgressUpdater::class.java),
+        foregroundUpdater: ForegroundUpdater = mock(ForegroundUpdater::class.java)
+    ) = WorkerParameters(
+        UUID.randomUUID(),
+        Data.EMPTY,
+        emptyList(),
+        WorkerParameters.RuntimeExtras(),
+        1,
+        executor,
+        RxWorkerTest.InstantWorkTaskExecutor(),
+        WorkerFactory.getDefaultWorkerFactory(),
+        progressUpdater,
+        foregroundUpdater
+    )
+}
+
+private class WorkerForeground(
+    appContext: Context,
+    workerParams: WorkerParameters
+) : RxWorker(appContext, workerParams) {
+    override fun createWork(): Single<Result> {
+        throw UnsupportedOperationException()
+    }
+}
\ No newline at end of file
diff --git a/work/work-rxjava3/api/current.txt b/work/work-rxjava3/api/current.txt
index 9293340..944514c 100644
--- a/work/work-rxjava3/api/current.txt
+++ b/work/work-rxjava3/api/current.txt
@@ -5,6 +5,7 @@
     ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
     method @MainThread public abstract io.reactivex.rxjava3.core.Single<androidx.work.ListenableWorker.Result!> createWork();
     method protected io.reactivex.rxjava3.core.Scheduler getBackgroundScheduler();
+    method public io.reactivex.rxjava3.core.Single<androidx.work.ForegroundInfo!> getForegroundInfo();
     method public final io.reactivex.rxjava3.core.Completable setCompletableProgress(androidx.work.Data);
     method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
   }
diff --git a/work/work-rxjava3/api/public_plus_experimental_current.txt b/work/work-rxjava3/api/public_plus_experimental_current.txt
index 9293340..944514c 100644
--- a/work/work-rxjava3/api/public_plus_experimental_current.txt
+++ b/work/work-rxjava3/api/public_plus_experimental_current.txt
@@ -5,6 +5,7 @@
     ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
     method @MainThread public abstract io.reactivex.rxjava3.core.Single<androidx.work.ListenableWorker.Result!> createWork();
     method protected io.reactivex.rxjava3.core.Scheduler getBackgroundScheduler();
+    method public io.reactivex.rxjava3.core.Single<androidx.work.ForegroundInfo!> getForegroundInfo();
     method public final io.reactivex.rxjava3.core.Completable setCompletableProgress(androidx.work.Data);
     method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
   }
diff --git a/work/work-rxjava3/api/restricted_current.txt b/work/work-rxjava3/api/restricted_current.txt
index 9293340..944514c 100644
--- a/work/work-rxjava3/api/restricted_current.txt
+++ b/work/work-rxjava3/api/restricted_current.txt
@@ -5,6 +5,7 @@
     ctor public RxWorker(android.content.Context, androidx.work.WorkerParameters);
     method @MainThread public abstract io.reactivex.rxjava3.core.Single<androidx.work.ListenableWorker.Result!> createWork();
     method protected io.reactivex.rxjava3.core.Scheduler getBackgroundScheduler();
+    method public io.reactivex.rxjava3.core.Single<androidx.work.ForegroundInfo!> getForegroundInfo();
     method public final io.reactivex.rxjava3.core.Completable setCompletableProgress(androidx.work.Data);
     method public final com.google.common.util.concurrent.ListenableFuture<androidx.work.ListenableWorker.Result!> startWork();
   }
diff --git a/work/work-rxjava3/build.gradle b/work/work-rxjava3/build.gradle
index 6be9b57..98f7df9 100644
--- a/work/work-rxjava3/build.gradle
+++ b/work/work-rxjava3/build.gradle
@@ -26,6 +26,7 @@
 dependencies {
     api(project(":work:work-runtime"))
     api(libs.rxjava3)
+    testImplementation(libs.truth)
     testImplementation(libs.junit)
     testImplementation(libs.kotlinStdlib)
     testImplementation(libs.mockitoCore)
diff --git a/work/work-rxjava3/src/main/java/androidx/work/rxjava3/RxWorker.java b/work/work-rxjava3/src/main/java/androidx/work/rxjava3/RxWorker.java
index 39b0435..5c34476 100644
--- a/work/work-rxjava3/src/main/java/androidx/work/rxjava3/RxWorker.java
+++ b/work/work-rxjava3/src/main/java/androidx/work/rxjava3/RxWorker.java
@@ -24,8 +24,11 @@
 import androidx.annotation.Nullable;
 import androidx.work.Configuration;
 import androidx.work.Data;
+import androidx.work.ForegroundInfo;
 import androidx.work.ListenableWorker;
+import androidx.work.OutOfQuotaPolicy;
 import androidx.work.WorkManager;
+import androidx.work.WorkRequest;
 import androidx.work.Worker;
 import androidx.work.WorkerParameters;
 import androidx.work.impl.utils.SynchronousExecutor;
@@ -77,17 +80,7 @@
     @Override
     public final ListenableFuture<Result> startWork() {
         mSingleFutureObserverAdapter = new SingleFutureAdapter<>();
-
-        final Scheduler scheduler = getBackgroundScheduler();
-        createWork()
-                .subscribeOn(scheduler)
-                // observe on WM's private thread
-                .observeOn(Schedulers.from(
-                        getTaskExecutor().getBackgroundExecutor(),
-                        /* interruptible */true,
-                        /* fair */true))
-                .subscribe(mSingleFutureObserverAdapter);
-        return mSingleFutureObserverAdapter.mFuture;
+        return convert(mSingleFutureObserverAdapter, createWork());
     }
 
     /**
@@ -151,6 +144,49 @@
         }
     }
 
+    @NonNull
+    @Override
+    public ListenableFuture<ForegroundInfo> getForegroundInfoAsync() {
+        return convert(new SingleFutureAdapter<>(), getForegroundInfo());
+    }
+
+    /**
+     * Return an {@code Single} with an instance of {@link ForegroundInfo} if the
+     * {@link WorkRequest} is
+     * important to the user.  In this case, WorkManager provides a signal to the OS that the
+     * process should be kept alive while this work is executing.
+     * <p>
+     * Prior to Android S, WorkManager manages and runs a foreground service on your behalf to
+     * execute the WorkRequest, showing the notification provided in the {@link ForegroundInfo}.
+     * To update this notification subsequently, the application can use
+     * {@link android.app.NotificationManager}.
+     * <p>
+     * Starting in Android S and above, WorkManager manages this WorkRequest using an immediate job.
+     *
+     * @return A {@link Single} of {@link ForegroundInfo} instance if the WorkRequest
+     * is marked immediate. For more information look at
+     * {@link WorkRequest.Builder#setExpedited(OutOfQuotaPolicy)}.
+     */
+    @NonNull
+    public Single<ForegroundInfo> getForegroundInfo() {
+        String message =
+                "Expedited WorkRequests require a RxWorker to provide an implementation for"
+                        + " `getForegroundInfo()`";
+        return Single.error(new IllegalStateException(message));
+    }
+
+    private <T> ListenableFuture<T> convert(SingleFutureAdapter<T> adapter, Single<T> single) {
+        final Scheduler scheduler = getBackgroundScheduler();
+        single.subscribeOn(scheduler)
+                // observe on WM's private thread
+                .observeOn(Schedulers.from(
+                        getTaskExecutor().getBackgroundExecutor(),
+                        /* interruptible */true,
+                        /* fair */true))
+                .subscribe(adapter);
+        return adapter.mFuture;
+    }
+
     /**
      * An observer that can observe a single and provide it as a {@link ListenableWorker}.
      */
diff --git a/work/work-rxjava3/src/test/java/androidx/work/rxjava3/RxForegroundInfoTest.kt b/work/work-rxjava3/src/test/java/androidx/work/rxjava3/RxForegroundInfoTest.kt
new file mode 100644
index 0000000..8d2f33c
--- /dev/null
+++ b/work/work-rxjava3/src/test/java/androidx/work/rxjava3/RxForegroundInfoTest.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2021 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.rxjava3
+
+import android.app.Notification
+import android.content.Context
+import androidx.work.Data
+import androidx.work.ForegroundInfo
+import androidx.work.ForegroundUpdater
+import androidx.work.ProgressUpdater
+import androidx.work.WorkerFactory
+import androidx.work.WorkerParameters
+import androidx.work.impl.utils.SynchronousExecutor
+import com.google.common.truth.Truth
+import io.reactivex.rxjava3.core.Single
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mockito.mock
+import java.util.UUID
+import java.util.concurrent.Executor
+
+@RunWith(JUnit4::class)
+class RxForegroundInfoTest {
+    @Test
+    fun testForegroundInfo() {
+        val context = mock(Context::class.java)
+        val foregroundInfo = WorkerForeground(context, createWorkerParams())
+            .foregroundInfoAsync.get()
+        Truth.assertThat(foregroundInfo).isEqualTo(testForegroundInfo)
+    }
+}
+
+private val testForegroundInfo = ForegroundInfo(10, mock(Notification::class.java))
+
+private class WorkerForeground(
+    appContext: Context,
+    workerParams: WorkerParameters
+) : RxWorker(appContext, workerParams) {
+    override fun createWork(): Single<Result> {
+        throw UnsupportedOperationException()
+    }
+
+    override fun getForegroundInfo(): Single<ForegroundInfo> = Single.just(testForegroundInfo)
+}
+
+private fun createWorkerParams(
+    executor: Executor = SynchronousExecutor(),
+    progressUpdater: ProgressUpdater = mock(ProgressUpdater::class.java),
+    foregroundUpdater: ForegroundUpdater = mock(ForegroundUpdater::class.java)
+) = WorkerParameters(
+    UUID.randomUUID(),
+    Data.EMPTY,
+    emptyList(),
+    WorkerParameters.RuntimeExtras(),
+    1,
+    executor,
+    RxWorkerTest.InstantWorkTaskExecutor(),
+    WorkerFactory.getDefaultWorkerFactory(),
+    progressUpdater,
+    foregroundUpdater
+)