summaryrefslogtreecommitdiff
path: root/java/com/android/dialer/common
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/dialer/common')
-rw-r--r--java/com/android/dialer/common/Assert.java5
-rw-r--r--java/com/android/dialer/common/ConfigProvider.java27
-rw-r--r--java/com/android/dialer/common/ConfigProviderBindings.java76
-rw-r--r--java/com/android/dialer/common/ConfigProviderFactory.java26
-rw-r--r--java/com/android/dialer/common/concurrent/DefaultDialerExecutorFactory.java111
-rw-r--r--java/com/android/dialer/common/concurrent/DialerExecutor.java10
-rw-r--r--java/com/android/dialer/common/concurrent/DialerUiTaskFragment.java94
-rw-r--r--java/com/android/dialer/common/concurrent/ThreadUtil.java5
8 files changed, 135 insertions, 219 deletions
diff --git a/java/com/android/dialer/common/Assert.java b/java/com/android/dialer/common/Assert.java
index 943e1ddcf..2d7f199ab 100644
--- a/java/com/android/dialer/common/Assert.java
+++ b/java/com/android/dialer/common/Assert.java
@@ -59,6 +59,11 @@ public class Assert {
}
@CheckReturnValue
+ public static AssertionError createAssertionFailException(String msg, Throwable reason) {
+ return new AssertionError(msg, reason);
+ }
+
+ @CheckReturnValue
public static UnsupportedOperationException createUnsupportedOperationFailException() {
return new UnsupportedOperationException();
}
diff --git a/java/com/android/dialer/common/ConfigProvider.java b/java/com/android/dialer/common/ConfigProvider.java
deleted file mode 100644
index c0791e979..000000000
--- a/java/com/android/dialer/common/ConfigProvider.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-/** Gets config values from the container application. */
-public interface ConfigProvider {
-
- String getString(String key, String defaultValue);
-
- long getLong(String key, long defaultValue);
-
- boolean getBoolean(String key, boolean defaultValue);
-}
diff --git a/java/com/android/dialer/common/ConfigProviderBindings.java b/java/com/android/dialer/common/ConfigProviderBindings.java
deleted file mode 100644
index 9f045add4..000000000
--- a/java/com/android/dialer/common/ConfigProviderBindings.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import android.content.Context;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-import android.support.v4.os.UserManagerCompat;
-
-/** Accessor for getting a {@link ConfigProvider}. */
-public class ConfigProviderBindings {
-
- private static ConfigProvider configProvider;
- private static ConfigProvider configProviderStub;
-
- public static ConfigProvider get(@NonNull Context context) {
- Assert.isNotNull(context);
- if (configProvider != null) {
- return configProvider;
- }
- if (!UserManagerCompat.isUserUnlocked(context)) {
- if (configProviderStub == null) {
- configProviderStub = new ConfigProviderStub();
- }
- return configProviderStub;
- }
-
- Context application = context.getApplicationContext();
- if (application instanceof ConfigProviderFactory) {
- configProvider = ((ConfigProviderFactory) application).getConfigProvider();
- }
-
- if (configProvider == null) {
- configProvider = new ConfigProviderStub();
- }
-
- return configProvider;
- }
-
- @VisibleForTesting
- public static void setForTesting(@Nullable ConfigProvider configProviderForTesting) {
- configProvider = configProviderForTesting;
- }
-
- private static class ConfigProviderStub implements ConfigProvider {
- @Override
- public String getString(String key, String defaultValue) {
- return defaultValue;
- }
-
- @Override
- public long getLong(String key, long defaultValue) {
- return defaultValue;
- }
-
- @Override
- public boolean getBoolean(String key, boolean defaultValue) {
- return defaultValue;
- }
- }
-}
diff --git a/java/com/android/dialer/common/ConfigProviderFactory.java b/java/com/android/dialer/common/ConfigProviderFactory.java
deleted file mode 100644
index aeb4f303a..000000000
--- a/java/com/android/dialer/common/ConfigProviderFactory.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-/**
- * This interface should be implementated by the Application subclass. It allows dialer code to get
- * references to a config provider.
- */
-public interface ConfigProviderFactory {
-
- ConfigProvider getConfigProvider();
-}
diff --git a/java/com/android/dialer/common/concurrent/DefaultDialerExecutorFactory.java b/java/com/android/dialer/common/concurrent/DefaultDialerExecutorFactory.java
index 4b6d81afd..82e517d9a 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,46 @@ 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 =
+ private static final Executor defaultParallelExecutor =
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 thread = new Thread(runnable, "NonUiTaskBuilder-Parallel");
thread.setPriority(4); // Corresponds to Process.THREAD_PRIORITY_BACKGROUND
return thread;
}
});
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 +197,7 @@ public class DefaultDialerExecutorFactory implements DialerExecutorFactory {
super.successListener,
super.failureListener,
serialExecutorService,
- parallelExecutorService);
+ parallelExecutor);
}
}
@@ -197,6 +215,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 +237,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/DialerUiTaskFragment.java b/java/com/android/dialer/common/concurrent/DialerUiTaskFragment.java
index 627336895..7f2a5a06b 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,8 +80,8 @@ 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 =
@@ -88,16 +92,11 @@ public final class DialerUiTaskFragment<InputT, OutputT> extends Fragment {
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,51 @@ 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(() -> 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(() -> 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/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) {