From ea7890cd5e829ed3f0b5f726561c569690af2030 Mon Sep 17 00:00:00 2001 From: Eric Erfanian Date: Mon, 19 Jun 2017 12:40:59 -0700 Subject: Update AOSP Dialer source from internal google3 repository at cl/159428781. Test: make, treehugger This CL updates the AOSP Dialer source with all the changes that have gone into the private google3 repository. This includes all the changes from cl/158012278 (6/05/2017) to cl/159428781 (6/19/2017). This goal of these drops is to keep the AOSP source in sync with the internal google3 repository. Currently these sync are done by hand with very minor modifications to the internal source code. See the Android.mk file for list of modifications. Our current goal is to do frequent drops (daily if possible) and eventually switched to an automated process. Merged-In: Ie60a84b3936efd0ea3d95d7c86bf96d2b1663030 Change-Id: If1fa394df2609f0d38b4f794c83f4db3f1006484 --- java/com/android/dialer/common/Assert.java | 5 + java/com/android/dialer/common/ConfigProvider.java | 27 ----- .../dialer/common/ConfigProviderBindings.java | 76 -------------- .../dialer/common/ConfigProviderFactory.java | 26 ----- .../concurrent/DefaultDialerExecutorFactory.java | 111 ++++++++++++++------- .../dialer/common/concurrent/DialerExecutor.java | 10 ++ .../common/concurrent/DialerUiTaskFragment.java | 94 ++++++++--------- .../dialer/common/concurrent/ThreadUtil.java | 5 + 8 files changed, 135 insertions(+), 219 deletions(-) delete mode 100644 java/com/android/dialer/common/ConfigProvider.java delete mode 100644 java/com/android/dialer/common/ConfigProviderBindings.java delete mode 100644 java/com/android/dialer/common/ConfigProviderFactory.java (limited to 'java/com/android/dialer/common') 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 @@ -58,6 +58,11 @@ public class Assert { return new AssertionError(msg); } + @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 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 extends BaseTaskBuilder { + 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 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 extends BaseTaskBuilder { - 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 worker) { - this(worker, defaultSerialExecutorService, defaultParallelExecutorService); + this(worker, defaultSerialExecutorService, defaultParallelExecutor); } public NonUiTaskBuilder( Worker 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); } } @@ -196,6 +214,11 @@ public class DefaultDialerExecutorFactory implements DialerExecutorFactory { dialerUiTaskFragment.executeSerial(input); } + @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 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 worker, SuccessListener 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 @@ -83,6 +83,16 @@ public interface DialerExecutor { @MainThread 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. + * + *

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 extends Fragment { - private String taskId; private Worker worker; private SuccessListener 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 extends Fragment { Worker worker, SuccessListener successListener, FailureListener failureListener, - @Nullable ExecutorService serialExecutorService, - @Nullable ExecutorService parallelExecutorService) { + @NonNull ScheduledExecutorService serialExecutorService, + @NonNull Executor parallelExecutor) { Assert.isMainThread(); DialerUiTaskFragment fragment = @@ -88,16 +92,11 @@ public final class DialerUiTaskFragment 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 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> { - - @SafeVarargs - @Override - protected final InternalTaskResult 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 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 { - - 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) { -- cgit v1.2.3