summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/common/concurrent
diff options
context:
space:
mode:
authorEric Erfanian <erfanian@google.com>2017-08-31 06:57:16 -0700
committerEric Erfanian <erfanian@google.com>2017-08-31 16:13:53 +0000
commit2ca4318cc1ee57dda907ba2069bd61d162b1baef (patch)
treee282668a9587cf6c1ec7b604dea860400c75c6c7 /java/com/android/dialer/common/concurrent
parent68038172793ee0e2ab3e2e56ddfbeb82879d1f58 (diff)
Update Dialer source to latest internal Google revision.
Previously, Android's Dialer app was developed in an internal Google source control system and only exported to public during AOSP drops. The Dialer team is now switching to a public development model similar to the telephony team. This CL represents all internal Google changes that were committed to Dialer between the public O release and today's tip of tree on internal master. This CL squashes those changes into a single commit. In subsequent changes, changes will be exported on a per-commit basis. Test: make, flash install, run Merged-In: I45270eaa8ce732d71a1bd84b08c7fa0e99af3160 Change-Id: I529aaeb88535b9533c0ae4ef4e6c1222d4e0f1c8 PiperOrigin-RevId: 167068436
Diffstat (limited to 'java/com/android/dialer/common/concurrent')
-rw-r--r--java/com/android/dialer/common/concurrent/DefaultDialerExecutorFactory.java121
-rw-r--r--java/com/android/dialer/common/concurrent/DialerExecutor.java10
-rw-r--r--java/com/android/dialer/common/concurrent/DialerExecutorComponent.java39
-rw-r--r--java/com/android/dialer/common/concurrent/DialerExecutorModule.java28
-rw-r--r--java/com/android/dialer/common/concurrent/DialerExecutors.java27
-rw-r--r--java/com/android/dialer/common/concurrent/DialerUiTaskFragment.java120
-rw-r--r--java/com/android/dialer/common/concurrent/FallibleAsyncTask.java2
-rw-r--r--java/com/android/dialer/common/concurrent/ThreadUtil.java5
8 files changed, 251 insertions, 101 deletions
diff --git a/java/com/android/dialer/common/concurrent/DefaultDialerExecutorFactory.java b/java/com/android/dialer/common/concurrent/DefaultDialerExecutorFactory.java
index 4b6d81afd..a87bbceb4 100644
--- a/java/com/android/dialer/common/concurrent/DefaultDialerExecutorFactory.java
+++ b/java/com/android/dialer/common/concurrent/DefaultDialerExecutorFactory.java
@@ -17,6 +17,7 @@
package com.android.dialer.common.concurrent;
import android.app.FragmentManager;
+import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.android.dialer.common.Assert;
@@ -25,9 +26,13 @@ import com.android.dialer.common.concurrent.DialerExecutor.Builder;
import com.android.dialer.common.concurrent.DialerExecutor.FailureListener;
import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
/** The production {@link DialerExecutorFactory}. */
@@ -62,16 +67,16 @@ public class DefaultDialerExecutorFactory implements DialerExecutorFactory {
throwable -> {
throw new RuntimeException(throwable);
};
- @Nullable final ExecutorService serialExecutorService;
- @Nullable final ExecutorService parallelExecutorService;
+ @Nullable final ScheduledExecutorService serialExecutorService;
+ @Nullable final Executor parallelExecutor;
BaseTaskBuilder(
Worker<InputT, OutputT> worker,
- @Nullable ExecutorService serialExecutorService,
- @Nullable ExecutorService parallelExecutorService) {
+ @Nullable ScheduledExecutorService serialExecutorService,
+ @Nullable Executor parallelExecutor) {
this.worker = worker;
this.serialExecutorService = serialExecutorService;
- this.parallelExecutorService = parallelExecutorService;
+ this.parallelExecutor = parallelExecutor;
}
@NonNull
@@ -91,6 +96,19 @@ public class DefaultDialerExecutorFactory implements DialerExecutorFactory {
/** Convenience class for use by {@link DialerExecutorFactory} implementations. */
public static class UiTaskBuilder<InputT, OutputT> extends BaseTaskBuilder<InputT, OutputT> {
+ private static final ScheduledExecutorService defaultSerialExecutorService =
+ Executors.newSingleThreadScheduledExecutor(
+ new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable runnable) {
+ LogUtil.i("UiTaskBuilder.newThread", "creating serial thread");
+ Thread thread = new Thread(runnable, "UiTaskBuilder-Serial");
+ thread.setPriority(5); // Corresponds to Process.THREAD_PRIORITY_DEFAULT
+ return thread;
+ }
+ });
+
+ private static final Executor defaultParallelExecutorService = AsyncTask.THREAD_POOL_EXECUTOR;
private final FragmentManager fragmentManager;
private final String id;
@@ -102,16 +120,16 @@ public class DefaultDialerExecutorFactory implements DialerExecutorFactory {
fragmentManager,
id,
worker,
- null /* serialExecutorService */,
- null /* parallelExecutorService */);
+ defaultSerialExecutorService,
+ defaultParallelExecutorService);
}
public UiTaskBuilder(
FragmentManager fragmentManager,
String id,
Worker<InputT, OutputT> worker,
- ExecutorService serialExecutor,
- ExecutorService parallelExecutor) {
+ ScheduledExecutorService serialExecutor,
+ Executor parallelExecutor) {
super(worker, serialExecutor, parallelExecutor);
this.fragmentManager = fragmentManager;
this.id = id;
@@ -128,46 +146,36 @@ public class DefaultDialerExecutorFactory implements DialerExecutorFactory {
super.successListener,
super.failureListener,
serialExecutorService,
- parallelExecutorService);
+ parallelExecutor);
return new UiDialerExecutor<>(dialerUiTaskFragment);
}
}
/** Convenience class for use by {@link DialerExecutorFactory} implementations. */
public static class NonUiTaskBuilder<InputT, OutputT> extends BaseTaskBuilder<InputT, OutputT> {
- private static final ExecutorService defaultSerialExecutorService =
- Executors.newSingleThreadExecutor(
+ private static final ScheduledExecutorService defaultSerialExecutorService =
+ Executors.newSingleThreadScheduledExecutor(
new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
LogUtil.i("NonUiTaskBuilder.newThread", "creating serial thread");
- Thread thread = new Thread(runnable, "NonUiTaskBuilder");
+ Thread thread = new Thread(runnable, "NonUiTaskBuilder-Serial");
thread.setPriority(4); // Corresponds to Process.THREAD_PRIORITY_BACKGROUND
return thread;
}
});
- private static final ExecutorService defaultParallelExecutorService =
- Executors.newFixedThreadPool(
- 5,
- new ThreadFactory() {
- @Override
- public Thread newThread(Runnable runnable) {
- LogUtil.i("NonUiTaskBuilder.newThread", "creating parallel thread");
- Thread thread = new Thread(runnable, "NonUiTaskBuilder");
- thread.setPriority(4); // Corresponds to Process.THREAD_PRIORITY_BACKGROUND
- return thread;
- }
- });
+ private static final Executor defaultParallelExecutor =
+ DialerExecutors.getLowPriorityThreadPool();
NonUiTaskBuilder(Worker<InputT, OutputT> worker) {
- this(worker, defaultSerialExecutorService, defaultParallelExecutorService);
+ this(worker, defaultSerialExecutorService, defaultParallelExecutor);
}
public NonUiTaskBuilder(
Worker<InputT, OutputT> worker,
- @NonNull ExecutorService serialExecutor,
- @NonNull ExecutorService parallelExecutor) {
+ @NonNull ScheduledExecutorService serialExecutor,
+ @NonNull Executor parallelExecutor) {
super(worker, Assert.isNotNull(serialExecutor), Assert.isNotNull(parallelExecutor));
}
@@ -179,7 +187,7 @@ public class DefaultDialerExecutorFactory implements DialerExecutorFactory {
super.successListener,
super.failureListener,
serialExecutorService,
- parallelExecutorService);
+ parallelExecutor);
}
}
@@ -197,6 +205,11 @@ public class DefaultDialerExecutorFactory implements DialerExecutorFactory {
}
@Override
+ public void executeSerialWithWait(@Nullable InputT input, long waitMillis) {
+ dialerUiTaskFragment.executeSerialWithWait(input, waitMillis);
+ }
+
+ @Override
public void executeParallel(@Nullable InputT input) {
dialerUiTaskFragment.executeParallel(input);
}
@@ -214,47 +227,59 @@ public class DefaultDialerExecutorFactory implements DialerExecutorFactory {
private final SuccessListener<OutputT> successListener;
private final FailureListener failureListener;
- private final ExecutorService serialExecutorService;
- private final ExecutorService parallelExecutorService;
+ private final ScheduledExecutorService serialExecutorService;
+ private final Executor parallelExecutor;
+
+ private ScheduledFuture<?> scheduledFuture;
NonUiDialerExecutor(
Worker<InputT, OutputT> worker,
SuccessListener<OutputT> successListener,
FailureListener failureListener,
- ExecutorService serialExecutorService,
- ExecutorService parallelExecutorService) {
+ ScheduledExecutorService serialExecutorService,
+ Executor parallelExecutor) {
this.worker = worker;
this.successListener = successListener;
this.failureListener = failureListener;
this.serialExecutorService = serialExecutorService;
- this.parallelExecutorService = parallelExecutorService;
+ this.parallelExecutor = parallelExecutor;
}
@Override
public void executeSerial(@Nullable InputT input) {
- executeOnCustomExecutorService(serialExecutorService, input);
+ serialExecutorService.execute(() -> run(input));
+ }
+
+ @Override
+ public void executeSerialWithWait(@Nullable InputT input, long waitMillis) {
+ if (scheduledFuture != null) {
+ LogUtil.i("NonUiDialerExecutor.executeSerialWithWait", "cancelling waiting task");
+ scheduledFuture.cancel(false /* mayInterrupt */);
+ }
+ scheduledFuture =
+ serialExecutorService.schedule(() -> run(input), waitMillis, TimeUnit.MILLISECONDS);
}
@Override
public void executeParallel(@Nullable InputT input) {
- executeOnCustomExecutorService(parallelExecutorService, input);
+ parallelExecutor.execute(() -> run(input));
}
@Override
public void executeOnCustomExecutorService(
@NonNull ExecutorService executorService, @Nullable InputT input) {
- Assert.isNotNull(executorService)
- .execute(
- () -> {
- OutputT output;
- try {
- output = worker.doInBackground(input);
- } catch (Throwable throwable) {
- ThreadUtil.postOnUiThread(() -> failureListener.onFailure(throwable));
- return;
- }
- ThreadUtil.postOnUiThread(() -> successListener.onSuccess(output));
- });
+ Assert.isNotNull(executorService).execute(() -> run(input));
+ }
+
+ private void run(@Nullable InputT input) {
+ OutputT output;
+ try {
+ output = worker.doInBackground(input);
+ } catch (Throwable throwable) {
+ ThreadUtil.postOnUiThread(() -> failureListener.onFailure(throwable));
+ return;
+ }
+ ThreadUtil.postOnUiThread(() -> successListener.onSuccess(output));
}
}
}
diff --git a/java/com/android/dialer/common/concurrent/DialerExecutor.java b/java/com/android/dialer/common/concurrent/DialerExecutor.java
index 0237e3a05..0414581d4 100644
--- a/java/com/android/dialer/common/concurrent/DialerExecutor.java
+++ b/java/com/android/dialer/common/concurrent/DialerExecutor.java
@@ -84,6 +84,16 @@ public interface DialerExecutor<InputT> {
void executeSerial(@Nullable InputT input);
/**
+ * Executes the task after waiting {@code waitMillis}. If called while the previous invocation is
+ * still waiting to be started, the original invocation is cancelled.
+ *
+ * <p>This is useful for tasks which might get scheduled many times in very quick succession, but
+ * it is only the last one that actually needs to be executed.
+ */
+ @MainThread
+ void executeSerialWithWait(@Nullable InputT input, long waitMillis);
+
+ /**
* Executes the task on a thread pool shared across the application. Multiple calls using this
* method may result in tasks being executed in parallel.
*/
diff --git a/java/com/android/dialer/common/concurrent/DialerExecutorComponent.java b/java/com/android/dialer/common/concurrent/DialerExecutorComponent.java
new file mode 100644
index 000000000..25033251f
--- /dev/null
+++ b/java/com/android/dialer/common/concurrent/DialerExecutorComponent.java
@@ -0,0 +1,39 @@
+/*
+ * 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 com.android.dialer.common.concurrent;
+
+import android.content.Context;
+import com.android.dialer.inject.HasRootComponent;
+import dagger.Subcomponent;
+
+/** Dagger component which provides a {@link DialerExecutorFactory}. */
+@Subcomponent
+public abstract class DialerExecutorComponent {
+
+ public abstract DialerExecutorFactory dialerExecutorFactory();
+
+ public static DialerExecutorComponent get(Context context) {
+ return ((DialerExecutorComponent.HasComponent)
+ ((HasRootComponent) context.getApplicationContext()).component())
+ .dialerExecutorComponent();
+ }
+
+ /** Used to refer to the root application component. */
+ public interface HasComponent {
+ DialerExecutorComponent dialerExecutorComponent();
+ }
+}
diff --git a/java/com/android/dialer/common/concurrent/DialerExecutorModule.java b/java/com/android/dialer/common/concurrent/DialerExecutorModule.java
new file mode 100644
index 000000000..281f88c15
--- /dev/null
+++ b/java/com/android/dialer/common/concurrent/DialerExecutorModule.java
@@ -0,0 +1,28 @@
+/*
+ * 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 com.android.dialer.common.concurrent;
+
+import dagger.Binds;
+import dagger.Module;
+
+/** Module which binds the production {@link DialerExecutorFactory}. */
+@Module
+public abstract class DialerExecutorModule {
+
+ @Binds
+ abstract DialerExecutorFactory bindDialerExecutorFactory(
+ DefaultDialerExecutorFactory defaultDialerExecutorFactory);
+}
diff --git a/java/com/android/dialer/common/concurrent/DialerExecutors.java b/java/com/android/dialer/common/concurrent/DialerExecutors.java
index 148d8660c..81b3c5cb3 100644
--- a/java/com/android/dialer/common/concurrent/DialerExecutors.java
+++ b/java/com/android/dialer/common/concurrent/DialerExecutors.java
@@ -19,7 +19,11 @@ package com.android.dialer.common.concurrent;
import android.app.FragmentManager;
import android.support.annotation.NonNull;
import com.android.dialer.common.Assert;
+import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
/**
* Factory methods for creating {@link DialerExecutor} objects for doing background work.
@@ -131,4 +135,27 @@ public final class DialerExecutors {
@NonNull Worker<InputT, OutputT> worker) {
return new DefaultDialerExecutorFactory().createNonUiTaskBuilder(Assert.isNotNull(worker));
}
+
+ private static final Executor lowPriorityThreadPool =
+ Executors.newFixedThreadPool(
+ 5,
+ new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable runnable) {
+ LogUtil.i("DialerExecutors.newThread", "creating low priority thread");
+ Thread thread = new Thread(runnable, "DialerExecutors-LowPriority");
+ thread.setPriority(4); // Corresponds to Process.THREAD_PRIORITY_BACKGROUND
+ return thread;
+ }
+ });
+
+ /**
+ * An application-wide thread pool used for low priority (non-UI) tasks.
+ *
+ * <p>This exists to prevent each individual dialer component from having to create its own
+ * threads/pools, which would result in the application having more threads than really necessary.
+ */
+ public static Executor getLowPriorityThreadPool() {
+ return lowPriorityThreadPool;
+ }
}
diff --git a/java/com/android/dialer/common/concurrent/DialerUiTaskFragment.java b/java/com/android/dialer/common/concurrent/DialerUiTaskFragment.java
index 627336895..f0b753758 100644
--- a/java/com/android/dialer/common/concurrent/DialerUiTaskFragment.java
+++ b/java/com/android/dialer/common/concurrent/DialerUiTaskFragment.java
@@ -18,17 +18,21 @@ package com.android.dialer.common.concurrent;
import android.app.Fragment;
import android.app.FragmentManager;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.MainThread;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.annotation.WorkerThread;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
-import com.android.dialer.common.concurrent.AsyncTaskExecutors.SimpleAsyncTaskExecutor;
import com.android.dialer.common.concurrent.DialerExecutor.FailureListener;
import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
+import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
/**
* Do not use this class directly. Instead use {@link DialerExecutors}.
@@ -38,13 +42,13 @@ import java.util.concurrent.ExecutorService;
*/
public final class DialerUiTaskFragment<InputT, OutputT> extends Fragment {
- private String taskId;
private Worker<InputT, OutputT> worker;
private SuccessListener<OutputT> successListener;
private FailureListener failureListener;
- private AsyncTaskExecutor serialExecutor = AsyncTaskExecutors.createAsyncTaskExecutor();
- private AsyncTaskExecutor parallelExecutor = AsyncTaskExecutors.createThreadPoolExecutor();
+ private ScheduledExecutorService serialExecutor;
+ private Executor parallelExecutor;
+ private ScheduledFuture<?> scheduledFuture;
/**
* Creates a new {@link DialerUiTaskFragment} or gets an existing one in the event that a
@@ -76,28 +80,23 @@ public final class DialerUiTaskFragment<InputT, OutputT> extends Fragment {
Worker<InputT, OutputT> worker,
SuccessListener<OutputT> successListener,
FailureListener failureListener,
- @Nullable ExecutorService serialExecutorService,
- @Nullable ExecutorService parallelExecutorService) {
+ @NonNull ScheduledExecutorService serialExecutorService,
+ @NonNull Executor parallelExecutor) {
Assert.isMainThread();
DialerUiTaskFragment<InputT, OutputT> fragment =
(DialerUiTaskFragment<InputT, OutputT>) fragmentManager.findFragmentByTag(taskId);
if (fragment == null) {
- LogUtil.i("DialerUiTaskFragment.create", "creating new DialerUiTaskFragment");
+ LogUtil.i("DialerUiTaskFragment.create", "creating new DialerUiTaskFragment for " + taskId);
fragment = new DialerUiTaskFragment<>();
fragmentManager.beginTransaction().add(fragment, taskId).commit();
}
- fragment.taskId = taskId;
fragment.worker = worker;
fragment.successListener = successListener;
fragment.failureListener = failureListener;
- if (serialExecutorService != null) {
- fragment.serialExecutor = new SimpleAsyncTaskExecutor(serialExecutorService);
- }
- if (parallelExecutorService != null) {
- fragment.parallelExecutor = new SimpleAsyncTaskExecutor(parallelExecutorService);
- }
+ fragment.serialExecutor = Assert.isNotNull(serialExecutorService);
+ fragment.parallelExecutor = Assert.isNotNull(parallelExecutor);
return fragment;
}
@@ -111,60 +110,75 @@ public final class DialerUiTaskFragment<InputT, OutputT> extends Fragment {
public void onDetach() {
super.onDetach();
LogUtil.enterBlock("DialerUiTaskFragment.onDetach");
- taskId = null;
successListener = null;
failureListener = null;
+ if (scheduledFuture != null) {
+ scheduledFuture.cancel(false /* mayInterrupt */);
+ scheduledFuture = null;
+ }
}
void executeSerial(InputT input) {
- serialExecutor.submit(taskId, new InternalTask(), input);
+ serialExecutor.execute(() -> runTask(input));
+ }
+
+ void executeSerialWithWait(InputT input, long waitMillis) {
+ if (scheduledFuture != null) {
+ LogUtil.i("DialerUiTaskFragment.executeSerialWithWait", "cancelling waiting task");
+ scheduledFuture.cancel(false /* mayInterrupt */);
+ }
+ scheduledFuture =
+ serialExecutor.schedule(() -> runTask(input), waitMillis, TimeUnit.MILLISECONDS);
}
void executeParallel(InputT input) {
- parallelExecutor.submit(taskId, new InternalTask(), input);
+ parallelExecutor.execute(() -> runTask(input));
}
void executeOnCustomExecutor(ExecutorService executor, InputT input) {
- new SimpleAsyncTaskExecutor(executor).submit(taskId, new InternalTask(), input);
+ executor.execute(() -> runTask(input));
}
- private final class InternalTask extends AsyncTask<InputT, Void, InternalTaskResult<OutputT>> {
-
- @SafeVarargs
- @Override
- protected final InternalTaskResult<OutputT> doInBackground(InputT... params) {
- try {
- return new InternalTaskResult<>(null, worker.doInBackground(params[0]));
- } catch (Throwable throwable) {
- LogUtil.e("InternalTask.doInBackground", "task failed", throwable);
- return new InternalTaskResult<>(throwable, null);
+ @WorkerThread
+ private void runTask(@Nullable InputT input) {
+ try {
+ OutputT output = worker.doInBackground(input);
+ if (successListener == null) {
+ LogUtil.i("DialerUiTaskFragment.runTask", "task succeeded but UI is dead");
+ } else {
+ ThreadUtil.postOnUiThread(
+ () -> {
+ // Even though there is a null check above, it is possible for the activity/fragment
+ // to be finished between the time the runnable is posted and the time it executes. Do
+ // an additional check here.
+ if (successListener == null) {
+ LogUtil.i(
+ "DialerUiTaskFragment.runTask",
+ "task succeeded but UI died after success runnable posted");
+ } else {
+ successListener.onSuccess(output);
+ }
+ });
}
- }
-
- @Override
- protected void onPostExecute(InternalTaskResult<OutputT> result) {
- if (result.throwable != null) {
- if (failureListener == null) {
- LogUtil.i("InternalTask.onPostExecute", "task failed but UI is dead");
- } else {
- failureListener.onFailure(result.throwable);
- }
- } else if (successListener == null) {
- LogUtil.i("InternalTask.onPostExecute", "task succeeded but UI is dead");
+ } catch (Throwable throwable) {
+ LogUtil.e("DialerUiTaskFragment.runTask", "task failed", throwable);
+ if (failureListener == null) {
+ LogUtil.i("DialerUiTaskFragment.runTask", "task failed but UI is dead");
} else {
- successListener.onSuccess(result.result);
+ ThreadUtil.postOnUiThread(
+ () -> {
+ // Even though there is a null check above, it is possible for the activity/fragment
+ // to be finished between the time the runnable is posted and the time it executes. Do
+ // an additional check here.
+ if (failureListener == null) {
+ LogUtil.i(
+ "DialerUiTaskFragment.runTask",
+ "task failed but UI died after failure runnable posted");
+ } else {
+ failureListener.onFailure(throwable);
+ }
+ });
}
}
}
-
- private static class InternalTaskResult<OutputT> {
-
- private final Throwable throwable;
- private final OutputT result;
-
- InternalTaskResult(Throwable throwable, OutputT result) {
- this.throwable = throwable;
- this.result = result;
- }
- }
}
diff --git a/java/com/android/dialer/common/concurrent/FallibleAsyncTask.java b/java/com/android/dialer/common/concurrent/FallibleAsyncTask.java
index 6d02fe67f..c7a7f36a6 100644
--- a/java/com/android/dialer/common/concurrent/FallibleAsyncTask.java
+++ b/java/com/android/dialer/common/concurrent/FallibleAsyncTask.java
@@ -30,7 +30,9 @@ import com.google.auto.value.AutoValue;
* @param <ParamsT> the type of the parameters sent to the task upon execution
* @param <ProgressT> the type of the progress units published during the background computation
* @param <ResultT> the type of the result of the background computation
+ * @deprecated Please use {@link DialerExecutors}.
*/
+@Deprecated
public abstract class FallibleAsyncTask<ParamsT, ProgressT, ResultT>
extends AsyncTask<ParamsT, ProgressT, FallibleTaskResult<ResultT>> {
diff --git a/java/com/android/dialer/common/concurrent/ThreadUtil.java b/java/com/android/dialer/common/concurrent/ThreadUtil.java
index 21cf4634e..39b6cceff 100644
--- a/java/com/android/dialer/common/concurrent/ThreadUtil.java
+++ b/java/com/android/dialer/common/concurrent/ThreadUtil.java
@@ -28,6 +28,11 @@ public class ThreadUtil {
getUiThreadHandler().post(runnable);
}
+ /** Posts a runnable to the UI thread, to be run after the specified amount of time elapses. */
+ public static void postDelayedOnUiThread(Runnable runnable, long delayMillis) {
+ getUiThreadHandler().postDelayed(runnable, delayMillis);
+ }
+
/** Gets a handler which uses the main looper. */
public static Handler getUiThreadHandler() {
if (mainThreadHandler == null) {