summaryrefslogtreecommitdiffstats
path: root/java/com/android/dialer/common
diff options
context:
space:
mode:
authorEric Erfanian <erfanian@google.com>2017-02-22 16:32:36 -0800
committerEric Erfanian <erfanian@google.com>2017-03-01 09:56:52 -0800
commitccca31529c07970e89419fb85a9e8153a5396838 (patch)
treea7034c0a01672b97728c13282a2672771cd28baa /java/com/android/dialer/common
parente7ae4624ba6f25cb8e648db74e0d64c0113a16ba (diff)
downloadandroid_packages_apps_Dialer-ccca31529c07970e89419fb85a9e8153a5396838.tar.gz
android_packages_apps_Dialer-ccca31529c07970e89419fb85a9e8153a5396838.tar.bz2
android_packages_apps_Dialer-ccca31529c07970e89419fb85a9e8153a5396838.zip
Update dialer sources.
Test: Built package and system image. This change clobbers the old source, and is an export from an internal Google repository. The internal repository was forked form Android in March, and this change includes modifications since then, to near the v8 release. Since the fork, we've moved code from monolithic to independent modules. In addition, we've switched to Blaze/Bazel as the build sysetm. This export, however, still uses make. New dependencies have been added: - Dagger - Auto-Value - Glide - Libshortcutbadger Going forward, development will still be in Google3, and the Gerrit release will become an automated export, with the next drop happening in ~ two weeks. Android.mk includes local modifications from ToT. Abridged changelog: Bug fixes ● Not able to mute, add a call when using Phone app in multiwindow mode ● Double tap on keypad triggering multiple key and tones ● Reported spam numbers not showing as spam in the call log ● Crash when user tries to block number while Phone app is not set as default ● Crash when user picks a number from search auto-complete list Visual Voicemail (VVM) improvements ● Share Voicemail audio via standard exporting mechanisms that support file attachment (email, MMS, etc.) ● Make phone number, email and web sites in VVM transcript clickable ● Set PIN before declining VVM Terms of Service {Carrier} ● Set client type for outbound visual voicemail SMS {Carrier} New incoming call and incall UI on older devices (Android M) ● Updated Phone app icon ● New incall UI (large buttons, button labels) ● New and animated Answer/Reject gestures Accessibility ● Add custom answer/decline call buttons on answer screen for touch exploration accessibility services ● Increase size of touch target ● Add verbal feedback when a Voicemail fails to load ● Fix pressing of Phone buttons while in a phone call using Switch Access ● Fix selecting and opening contacts in talkback mode ● Split focus for ‘Learn More’ link in caller id & spam to help distinguish similar text Other ● Backup & Restore for App Preferences ● Prompt user to enable Wi-Fi calling if the call ends due to out of service and Wi-Fi is connected ● Rename “Dialpad” to “Keypad” ● Show "Private number" for restricted calls ● Delete unused items (vcard, add contact, call history) from Phone menu Change-Id: I2a7e53532a24c21bf308bf0a6d178d7ddbca4958
Diffstat (limited to 'java/com/android/dialer/common')
-rw-r--r--java/com/android/dialer/common/AndroidManifest.xml3
-rw-r--r--java/com/android/dialer/common/Assert.java185
-rw-r--r--java/com/android/dialer/common/AsyncTaskExecutor.java51
-rw-r--r--java/com/android/dialer/common/AsyncTaskExecutors.java91
-rw-r--r--java/com/android/dialer/common/AutoValue_FallibleAsyncTask_FallibleTaskResult.java79
-rw-r--r--java/com/android/dialer/common/ConfigProvider.java27
-rw-r--r--java/com/android/dialer/common/ConfigProviderBindings.java68
-rw-r--r--java/com/android/dialer/common/ConfigProviderFactory.java26
-rw-r--r--java/com/android/dialer/common/DpUtil.java31
-rw-r--r--java/com/android/dialer/common/FallibleAsyncTask.java94
-rw-r--r--java/com/android/dialer/common/FragmentUtils.java98
-rw-r--r--java/com/android/dialer/common/LogUtil.java214
-rw-r--r--java/com/android/dialer/common/MathUtil.java57
-rw-r--r--java/com/android/dialer/common/NetworkUtil.java192
-rw-r--r--java/com/android/dialer/common/UiUtil.java41
-rw-r--r--java/com/android/dialer/common/res/values/strings.xml5
16 files changed, 1262 insertions, 0 deletions
diff --git a/java/com/android/dialer/common/AndroidManifest.xml b/java/com/android/dialer/common/AndroidManifest.xml
new file mode 100644
index 000000000..ae43d6693
--- /dev/null
+++ b/java/com/android/dialer/common/AndroidManifest.xml
@@ -0,0 +1,3 @@
+<manifest
+ package="com.android.dialer.common">
+</manifest>
diff --git a/java/com/android/dialer/common/Assert.java b/java/com/android/dialer/common/Assert.java
new file mode 100644
index 000000000..00b4f2595
--- /dev/null
+++ b/java/com/android/dialer/common/Assert.java
@@ -0,0 +1,185 @@
+/*
+ * 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.os.Looper;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+/** Assertions which will result in program termination unless disabled by flags. */
+public class Assert {
+
+ private static boolean areThreadAssertsEnabled = true;
+
+ public static void setAreThreadAssertsEnabled(boolean areThreadAssertsEnabled) {
+ Assert.areThreadAssertsEnabled = areThreadAssertsEnabled;
+ }
+
+ /**
+ * Called when a truly exceptional case occurs.
+ *
+ * @throws AssertionError
+ */
+ public static void fail() {
+ throw new AssertionError("Fail");
+ }
+
+ /**
+ * Called when a truly exceptional case occurs.
+ *
+ * @param reason the optional reason to supply as the exception message
+ * @throws AssertionError
+ */
+ public static void fail(String reason) {
+ throw new AssertionError(reason);
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @throws IllegalArgumentException if {@code expression} is false
+ */
+ public static void checkArgument(boolean expression) {
+ checkArgument(expression, null);
+ }
+
+ /**
+ * Ensures the truth of an expression involving one or more parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @param messageTemplate the message to log, possible with format arguments.
+ * @param args optional arguments to be used in the formatted string.
+ * @throws IllegalArgumentException if {@code expression} is false
+ */
+ public static void checkArgument(
+ boolean expression, @Nullable String messageTemplate, Object... args) {
+ if (!expression) {
+ throw new IllegalArgumentException(format(messageTemplate, args));
+ }
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling instance, but not
+ * involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ public static void checkState(boolean expression) {
+ checkState(expression, null);
+ }
+
+ /**
+ * Ensures the truth of an expression involving the state of the calling instance, but not
+ * involving any parameters to the calling method.
+ *
+ * @param expression a boolean expression
+ * @param messageTemplate the message to log, possible with format arguments.
+ * @param args optional arguments to be used in the formatted string.
+ * @throws IllegalStateException if {@code expression} is false
+ */
+ public static void checkState(
+ boolean expression, @Nullable String messageTemplate, Object... args) {
+ if (!expression) {
+ throw new IllegalStateException(format(messageTemplate, args));
+ }
+ }
+
+ /**
+ * Ensures that an object reference passed as a parameter to the calling method is not null.
+ *
+ * @param reference an object reference
+ * @return the non-null reference that was validated
+ * @throws NullPointerException if {@code reference} is null
+ */
+ @NonNull
+ public static <T> T isNotNull(@Nullable T reference) {
+ return isNotNull(reference, null);
+ }
+
+ /**
+ * Ensures that an object reference passed as a parameter to the calling method is not null.
+ *
+ * @param reference an object reference
+ * @param messageTemplate the message to log, possible with format arguments.
+ * @param args optional arguments to be used in the formatted string.
+ * @return the non-null reference that was validated
+ * @throws NullPointerException if {@code reference} is null
+ */
+ @NonNull
+ public static <T> T isNotNull(
+ @Nullable T reference, @Nullable String messageTemplate, Object... args) {
+ if (reference == null) {
+ throw new NullPointerException(format(messageTemplate, args));
+ }
+ return reference;
+ }
+
+ /**
+ * Ensures that the current thread is the main thread.
+ *
+ * @throws IllegalStateException if called on a background thread
+ */
+ public static void isMainThread() {
+ isMainThread(null);
+ }
+
+ /**
+ * Ensures that the current thread is the main thread.
+ *
+ * @param messageTemplate the message to log, possible with format arguments.
+ * @param args optional arguments to be used in the formatted string.
+ * @throws IllegalStateException if called on a background thread
+ */
+ public static void isMainThread(@Nullable String messageTemplate, Object... args) {
+ if (!areThreadAssertsEnabled) {
+ return;
+ }
+ checkState(Looper.getMainLooper().equals(Looper.myLooper()), messageTemplate, args);
+ }
+
+ /**
+ * Ensures that the current thread is a worker thread.
+ *
+ * @throws IllegalStateException if called on the main thread
+ */
+ public static void isWorkerThread() {
+ isWorkerThread(null);
+ }
+
+ /**
+ * Ensures that the current thread is a worker thread.
+ *
+ * @param messageTemplate the message to log, possible with format arguments.
+ * @param args optional arguments to be used in the formatted string.
+ * @throws IllegalStateException if called on the main thread
+ */
+ public static void isWorkerThread(@Nullable String messageTemplate, Object... args) {
+ if (!areThreadAssertsEnabled) {
+ return;
+ }
+ checkState(!Looper.getMainLooper().equals(Looper.myLooper()), messageTemplate, args);
+ }
+
+ private static String format(@Nullable String messageTemplate, Object... args) {
+ if (messageTemplate == null) {
+ return null;
+ }
+ return String.format(messageTemplate, args);
+ }
+}
diff --git a/java/com/android/dialer/common/AsyncTaskExecutor.java b/java/com/android/dialer/common/AsyncTaskExecutor.java
new file mode 100644
index 000000000..caadfe7ce
--- /dev/null
+++ b/java/com/android/dialer/common/AsyncTaskExecutor.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 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.os.AsyncTask;
+import android.support.annotation.MainThread;
+import java.util.concurrent.Executor;
+
+/**
+ * Interface used to submit {@link AsyncTask} objects to run in the background.
+ *
+ * <p>This interface has a direct parallel with the {@link Executor} interface. It exists to
+ * decouple the mechanics of AsyncTask submission from the description of how that AsyncTask will
+ * execute.
+ *
+ * <p>One immediate benefit of this approach is that testing becomes much easier, since it is easy
+ * to introduce a mock or fake AsyncTaskExecutor in unit/integration tests, and thus inspect which
+ * tasks have been submitted and control their execution in an orderly manner.
+ *
+ * <p>Another benefit in due course will be the management of the submitted tasks. An extension to
+ * this interface is planned to allow Activities to easily cancel all the submitted tasks that are
+ * still pending in the onDestroy() method of the Activity.
+ */
+public interface AsyncTaskExecutor {
+
+ /**
+ * Executes the given AsyncTask with the default Executor.
+ *
+ * <p>This method <b>must only be called from the ui thread</b>.
+ *
+ * <p>The identifier supplied is any Object that can be used to identify the task later. Most
+ * commonly this will be an enum which the tests can also refer to. {@code null} is also accepted,
+ * though of course this won't help in identifying the task later.
+ */
+ @MainThread
+ <T> AsyncTask<T, ?, ?> submit(Object identifier, AsyncTask<T, ?, ?> task, T... params);
+}
diff --git a/java/com/android/dialer/common/AsyncTaskExecutors.java b/java/com/android/dialer/common/AsyncTaskExecutors.java
new file mode 100644
index 000000000..77bebdb36
--- /dev/null
+++ b/java/com/android/dialer/common/AsyncTaskExecutors.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2011 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.os.AsyncTask;
+import android.support.annotation.MainThread;
+import java.util.concurrent.Executor;
+
+/**
+ * Factory methods for creating AsyncTaskExecutors.
+ *
+ * <p>All of the factory methods on this class check first to see if you have set a static {@link
+ * AsyncTaskExecutorFactory} set through the {@link #setFactoryForTest(AsyncTaskExecutorFactory)}
+ * method, and if so delegate to that instead, which is one way of injecting dependencies for
+ * testing classes whose construction cannot be controlled such as {@link android.app.Activity}.
+ */
+public final class AsyncTaskExecutors {
+
+ /**
+ * A single instance of the {@link AsyncTaskExecutorFactory}, to which we delegate if it is
+ * non-null, for injecting when testing.
+ */
+ private static AsyncTaskExecutorFactory mInjectedAsyncTaskExecutorFactory = null;
+
+ /**
+ * Creates an AsyncTaskExecutor that submits tasks to run with {@link AsyncTask#SERIAL_EXECUTOR}.
+ */
+ public static AsyncTaskExecutor createAsyncTaskExecutor() {
+ synchronized (AsyncTaskExecutors.class) {
+ if (mInjectedAsyncTaskExecutorFactory != null) {
+ return mInjectedAsyncTaskExecutorFactory.createAsyncTaskExeuctor();
+ }
+ return new SimpleAsyncTaskExecutor(AsyncTask.SERIAL_EXECUTOR);
+ }
+ }
+
+ /**
+ * Creates an AsyncTaskExecutor that submits tasks to run with {@link
+ * AsyncTask#THREAD_POOL_EXECUTOR}.
+ */
+ public static AsyncTaskExecutor createThreadPoolExecutor() {
+ synchronized (AsyncTaskExecutors.class) {
+ if (mInjectedAsyncTaskExecutorFactory != null) {
+ return mInjectedAsyncTaskExecutorFactory.createAsyncTaskExeuctor();
+ }
+ return new SimpleAsyncTaskExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+ }
+ }
+
+ public static void setFactoryForTest(AsyncTaskExecutorFactory factory) {
+ synchronized (AsyncTaskExecutors.class) {
+ mInjectedAsyncTaskExecutorFactory = factory;
+ }
+ }
+
+ /** Interface for creating AsyncTaskExecutor objects. */
+ public interface AsyncTaskExecutorFactory {
+
+ AsyncTaskExecutor createAsyncTaskExeuctor();
+ }
+
+ private static class SimpleAsyncTaskExecutor implements AsyncTaskExecutor {
+
+ private final Executor mExecutor;
+
+ public SimpleAsyncTaskExecutor(Executor executor) {
+ mExecutor = executor;
+ }
+
+ @Override
+ @MainThread
+ public <T> AsyncTask<T, ?, ?> submit(Object identifer, AsyncTask<T, ?, ?> task, T... params) {
+ Assert.isMainThread();
+ return task.executeOnExecutor(mExecutor, params);
+ }
+ }
+}
diff --git a/java/com/android/dialer/common/AutoValue_FallibleAsyncTask_FallibleTaskResult.java b/java/com/android/dialer/common/AutoValue_FallibleAsyncTask_FallibleTaskResult.java
new file mode 100644
index 000000000..f9d7cea90
--- /dev/null
+++ b/java/com/android/dialer/common/AutoValue_FallibleAsyncTask_FallibleTaskResult.java
@@ -0,0 +1,79 @@
+/*
+ * 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.support.annotation.Nullable;
+import javax.annotation.Generated;
+
+
+ final class AutoValue_FallibleAsyncTask_FallibleTaskResult<ResultT> extends FallibleAsyncTask.FallibleTaskResult<ResultT> {
+
+ private final Throwable throwable;
+ private final ResultT result;
+
+ AutoValue_FallibleAsyncTask_FallibleTaskResult(
+ @Nullable Throwable throwable,
+ @Nullable ResultT result) {
+ this.throwable = throwable;
+ this.result = result;
+ }
+
+ @Nullable
+ @Override
+ public Throwable getThrowable() {
+ return throwable;
+ }
+
+ @Nullable
+ @Override
+ public ResultT getResult() {
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "FallibleTaskResult{"
+ + "throwable=" + throwable + ", "
+ + "result=" + result
+ + "}";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (o instanceof FallibleAsyncTask.FallibleTaskResult) {
+ FallibleAsyncTask.FallibleTaskResult<?> that = (FallibleAsyncTask.FallibleTaskResult<?>) o;
+ return ((this.throwable == null) ? (that.getThrowable() == null) : this.throwable.equals(that.getThrowable()))
+ && ((this.result == null) ? (that.getResult() == null) : this.result.equals(that.getResult()));
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ int h = 1;
+ h *= 1000003;
+ h ^= (throwable == null) ? 0 : this.throwable.hashCode();
+ h *= 1000003;
+ h ^= (result == null) ? 0 : this.result.hashCode();
+ return h;
+ }
+
+}
+
diff --git a/java/com/android/dialer/common/ConfigProvider.java b/java/com/android/dialer/common/ConfigProvider.java
new file mode 100644
index 000000000..c0791e979
--- /dev/null
+++ b/java/com/android/dialer/common/ConfigProvider.java
@@ -0,0 +1,27 @@
+/*
+ * 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
new file mode 100644
index 000000000..92e6cc3ff
--- /dev/null
+++ b/java/com/android/dialer/common/ConfigProviderBindings.java
@@ -0,0 +1,68 @@
+/*
+ * 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;
+
+/** Accessor for getting a {@link ConfigProvider}. */
+public class ConfigProviderBindings {
+
+ private static ConfigProvider configProvider;
+
+ public static ConfigProvider get(@NonNull Context context) {
+ Assert.isNotNull(context);
+ if (configProvider != null) {
+ return configProvider;
+ }
+
+ 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
new file mode 100644
index 000000000..aeb4f303a
--- /dev/null
+++ b/java/com/android/dialer/common/ConfigProviderFactory.java
@@ -0,0 +1,26 @@
+/*
+ * 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/DpUtil.java b/java/com/android/dialer/common/DpUtil.java
new file mode 100644
index 000000000..0388824cd
--- /dev/null
+++ b/java/com/android/dialer/common/DpUtil.java
@@ -0,0 +1,31 @@
+/*
+ * 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;
+
+/** Utility for dp to px conversion */
+public class DpUtil {
+
+ public static float pxToDp(Context context, float px) {
+ return px / context.getResources().getDisplayMetrics().density;
+ }
+
+ public static float dpToPx(Context context, float dp) {
+ return dp * context.getResources().getDisplayMetrics().density;
+ }
+}
diff --git a/java/com/android/dialer/common/FallibleAsyncTask.java b/java/com/android/dialer/common/FallibleAsyncTask.java
new file mode 100644
index 000000000..fbdbda75f
--- /dev/null
+++ b/java/com/android/dialer/common/FallibleAsyncTask.java
@@ -0,0 +1,94 @@
+/*
+ * 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;
+
+import android.os.AsyncTask;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import com.android.dialer.common.FallibleAsyncTask.FallibleTaskResult;
+
+
+/**
+ * A task that runs work in the background, passing Throwables from {@link
+ * #doInBackground(Object[])} to {@link #onPostExecute(Object)} through a {@link
+ * FallibleTaskResult}.
+ *
+ * @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
+ */
+public abstract class FallibleAsyncTask<ParamsT, ProgressT, ResultT>
+ extends AsyncTask<ParamsT, ProgressT, FallibleTaskResult<ResultT>> {
+
+ @Override
+ protected final FallibleTaskResult<ResultT> doInBackground(ParamsT... params) {
+ try {
+ return FallibleTaskResult.createSuccessResult(doInBackgroundFallible(params));
+ } catch (Throwable t) {
+ return FallibleTaskResult.createFailureResult(t);
+ }
+ }
+
+ /** Performs background work that may result in a Throwable. */
+ @Nullable
+ protected abstract ResultT doInBackgroundFallible(ParamsT... params) throws Throwable;
+
+ /**
+ * Holds the result of processing from {@link #doInBackground(Object[])}.
+ *
+ * @param <ResultT> the type of the result of the background computation
+ */
+
+ protected abstract static class FallibleTaskResult<ResultT> {
+
+ /** Creates an instance of FallibleTaskResult for the given throwable. */
+ private static <ResultT> FallibleTaskResult<ResultT> createFailureResult(@NonNull Throwable t) {
+ return new AutoValue_FallibleAsyncTask_FallibleTaskResult<>(t, null);
+ }
+
+ /** Creates an instance of FallibleTaskResult for the given result. */
+ private static <ResultT> FallibleTaskResult<ResultT> createSuccessResult(
+ @Nullable ResultT result) {
+ return new AutoValue_FallibleAsyncTask_FallibleTaskResult<>(null, result);
+ }
+
+ /**
+ * Returns the Throwable thrown in {@link #doInBackground(Object[])}, or {@code null} if
+ * background work completed without throwing.
+ */
+ @Nullable
+ public abstract Throwable getThrowable();
+
+ /**
+ * Returns the result of {@link #doInBackground(Object[])}, which may be {@code null}, or {@code
+ * null} if the background work threw a Throwable.
+ *
+ * <p>Use {@link #isFailure()} to determine if a {@code null} return is the result of a
+ * Throwable from the background work.
+ */
+ @Nullable
+ public abstract ResultT getResult();
+
+ /**
+ * Returns {@code true} if this object is the result of background work that threw a Throwable.
+ */
+ public boolean isFailure() {
+ //noinspection ThrowableResultOfMethodCallIgnored
+ return getThrowable() != null;
+ }
+ }
+}
diff --git a/java/com/android/dialer/common/FragmentUtils.java b/java/com/android/dialer/common/FragmentUtils.java
new file mode 100644
index 000000000..cb036959d
--- /dev/null
+++ b/java/com/android/dialer/common/FragmentUtils.java
@@ -0,0 +1,98 @@
+/*
+ * 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.support.annotation.CheckResult;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentActivity;
+
+/** Utility methods for working with Fragments */
+public class FragmentUtils {
+
+ private static Object parentForTesting;
+
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ public static void setParentForTesting(Object parentForTesting) {
+ FragmentUtils.parentForTesting = parentForTesting;
+ }
+
+ /**
+ * @return The parent of frag that implements the callbackInterface or null if no such parent can
+ * be found
+ */
+ @CheckResult(suggest = "#checkParent(Fragment, Class)}")
+ @Nullable
+ public static <T> T getParent(@NonNull Fragment fragment, @NonNull Class<T> callbackInterface) {
+ if (callbackInterface.isInstance(parentForTesting)) {
+ @SuppressWarnings("unchecked") // Casts are checked using runtime methods
+ T parent = (T) parentForTesting;
+ return parent;
+ }
+
+ Fragment parentFragment = fragment.getParentFragment();
+ if (callbackInterface.isInstance(parentFragment)) {
+ @SuppressWarnings("unchecked") // Casts are checked using runtime methods
+ T parent = (T) parentFragment;
+ return parent;
+ } else {
+ FragmentActivity activity = fragment.getActivity();
+ if (callbackInterface.isInstance(activity)) {
+ @SuppressWarnings("unchecked") // Casts are checked using runtime methods
+ T parent = (T) activity;
+ return parent;
+ }
+ }
+ return null;
+ }
+
+ /** Returns the parent or throws. Should perform check elsewhere(e.g. onAttach, newInstance). */
+ @NonNull
+ public static <T> T getParentUnsafe(
+ @NonNull Fragment fragment, @NonNull Class<T> callbackInterface) {
+ return Assert.isNotNull(getParent(fragment, callbackInterface));
+ }
+
+ /**
+ * Ensures fragment has a parent that implements the corresponding interface
+ *
+ * @param frag The Fragment whose parents are to be checked
+ * @param callbackInterface The interface class that a parent should implement
+ * @throws IllegalStateException if no parents are found that implement callbackInterface
+ */
+ public static void checkParent(@NonNull Fragment frag, @NonNull Class<?> callbackInterface)
+ throws IllegalStateException {
+ if (parentForTesting != null) {
+ return;
+ }
+ if (FragmentUtils.getParent(frag, callbackInterface) == null) {
+ String parent =
+ frag.getParentFragment() == null
+ ? frag.getActivity().getClass().getName()
+ : frag.getParentFragment().getClass().getName();
+ throw new IllegalStateException(
+ frag.getClass().getName()
+ + " must be added to a parent"
+ + " that implements "
+ + callbackInterface.getName()
+ + ". Instead found "
+ + parent);
+ }
+ }
+}
diff --git a/java/com/android/dialer/common/LogUtil.java b/java/com/android/dialer/common/LogUtil.java
new file mode 100644
index 000000000..32d7b960b
--- /dev/null
+++ b/java/com/android/dialer/common/LogUtil.java
@@ -0,0 +1,214 @@
+/*
+ * 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.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.telephony.PhoneNumberUtils;
+import android.text.TextUtils;
+
+/** Provides logging functions. */
+public class LogUtil {
+
+ public static final String TAG = "Dialer";
+ private static final String SEPARATOR = " - ";
+
+ private LogUtil() {}
+
+ /**
+ * Log at a verbose level. Verbose logs should generally be filtered out, but may be useful when
+ * additional information is needed (e.g. to see how a particular flow evolved). These logs will
+ * not generally be available on production builds.
+ *
+ * @param tag An identifier to allow searching for related logs. Generally of the form
+ * 'Class.method'.
+ * @param msg The message you would like logged, possibly with format arguments.
+ * @param args Optional arguments to be used in the formatted string.
+ * @see {@link String#format(String, Object...)}
+ * @see {@link android.util.Log#v(String, String)}
+ */
+ public static void v(@NonNull String tag, @Nullable String msg, @Nullable Object... args) {
+ println(android.util.Log.VERBOSE, TAG, tag, msg, args);
+ }
+
+ /**
+ * Log at a debug level. Debug logs should provide known-useful information to aid in
+ * troubleshooting or evaluating flow. These logs will not generally be available on production
+ * builds.
+ *
+ * @param tag An identifier to allow searching for related logs. Generally of the form
+ * 'Class.method'
+ * @param msg The message you would like logged, possibly with format arguments
+ * @param args Optional arguments to be used in the formatted string
+ * @see {@link String#format(String, Object...)}
+ * @see {@link android.util.Log#d(String, String)}
+ */
+ public static void d(@NonNull String tag, @Nullable String msg, @Nullable Object... args) {
+ println(android.util.Log.DEBUG, TAG, tag, msg, args);
+ }
+
+ /**
+ * Log at an info level. Info logs provide information that would be useful to have on production
+ * builds for troubleshooting.
+ *
+ * @param tag An identifier to allow searching for related logs. Generally of the form
+ * 'Class.method'.
+ * @param msg The message you would like logged, possibly with format arguments.
+ * @param args Optional arguments to be used in the formatted string.
+ * @see {@link String#format(String, Object...)}
+ * @see {@link android.util.Log#i(String, String)}
+ */
+ public static void i(@NonNull String tag, @Nullable String msg, @Nullable Object... args) {
+ println(android.util.Log.INFO, TAG, tag, msg, args);
+ }
+
+ /**
+ * Log entry into a method at the info level.
+ *
+ * @param tag An identifier to allow searching for related logs. Generally of the form
+ * 'Class.method'.
+ */
+ public static void enterBlock(String tag) {
+ println(android.util.Log.INFO, TAG, tag, "enter");
+ }
+
+ /**
+ * Log at a warn level. Warn logs indicate a possible error (e.g. a default switch branch was hit,
+ * or a null object was expected to be non-null), but recovery is possible. This may be used when
+ * it is not guaranteed that an indeterminate or bad state was entered, just that something may
+ * have gone wrong.
+ *
+ * @param tag An identifier to allow searching for related logs. Generally of the form
+ * 'Class.method'.
+ * @param msg The message you would like logged, possibly with format arguments.
+ * @param args Optional arguments to be used in the formatted string.
+ * @see {@link String#format(String, Object...)}
+ * @see {@link android.util.Log#w(String, String)}
+ */
+ public static void w(@NonNull String tag, @Nullable String msg, @Nullable Object... args) {
+ println(android.util.Log.WARN, TAG, tag, msg, args);
+ }
+
+ /**
+ * Log at an error level. Error logs are used when it is known that an error occurred and is
+ * possibly fatal. This is used to log information that will be useful for troubleshooting a crash
+ * or other severe condition (e.g. error codes, state values, etc.).
+ *
+ * @param tag An identifier to allow searching for related logs. Generally of the form
+ * 'Class.method'.
+ * @param msg The message you would like logged, possibly with format arguments.
+ * @param args Optional arguments to be used in the formatted string.
+ * @see {@link String#format(String, Object...)}
+ * @see {@link android.util.Log#e(String, String)}
+ */
+ public static void e(@NonNull String tag, @Nullable String msg, @Nullable Object... args) {
+ println(android.util.Log.ERROR, TAG, tag, msg, args);
+ }
+
+ /**
+ * Log an exception at an error level. Error logs are used when it is known that an error occurred
+ * and is possibly fatal. This is used to log information that will be useful for troubleshooting
+ * a crash or other severe condition (e.g. error codes, state values, etc.).
+ *
+ * @param tag An identifier to allow searching for related logs. Generally of the form
+ * 'Class.method'.
+ * @param msg The message you would like logged.
+ * @param throwable The exception to log.
+ * @see {@link String#format(String, Object...)}
+ * @see {@link android.util.Log#e(String, String)}
+ */
+ public static void e(@NonNull String tag, @Nullable String msg, @NonNull Throwable throwable) {
+ if (!TextUtils.isEmpty(msg)) {
+ println(android.util.Log.ERROR, TAG, tag, msg);
+ }
+ println(android.util.Log.ERROR, TAG, tag, android.util.Log.getStackTraceString(throwable));
+ }
+
+ /**
+ * Used for log statements where we don't want to log various strings (e.g., usernames) with
+ * default logging to avoid leaking PII in logcat.
+ *
+ * @return text as is if {@value #TAG}'s log level is set to DEBUG or VERBOSE or on non-release
+ * builds; returns a redacted version otherwise.
+ */
+ public static String sanitizePii(@Nullable Object object) {
+ if (object == null) {
+ return "null";
+ }
+ if (isDebugEnabled()) {
+ return object.toString();
+ }
+ return "Redacted-" + object.toString().length() + "-chars";
+ }
+
+ /** Anonymizes char to prevent logging personally identifiable information. */
+ public static char sanitizeDialPadChar(char ch) {
+ if (isDebugEnabled()) {
+ return ch;
+ }
+ if (is12Key(ch)) {
+ return '*';
+ }
+ return ch;
+ }
+
+ /** Anonymizes the phone number to prevent logging personally identifiable information. */
+ public static String sanitizePhoneNumber(@Nullable String phoneNumber) {
+ if (isDebugEnabled()) {
+ return phoneNumber;
+ }
+ if (phoneNumber == null) {
+ return null;
+ }
+ StringBuilder stringBuilder = new StringBuilder(phoneNumber.length());
+ for (char c : phoneNumber.toCharArray()) {
+ stringBuilder.append(sanitizeDialPadChar(c));
+ }
+ return stringBuilder.toString();
+ }
+
+ public static boolean isVerboseEnabled() {
+ return android.util.Log.isLoggable(TAG, android.util.Log.VERBOSE);
+ }
+
+ public static boolean isDebugEnabled() {
+ return android.util.Log.isLoggable(TAG, android.util.Log.DEBUG);
+ }
+
+ private static boolean is12Key(char ch) {
+ return PhoneNumberUtils.is12Key(ch);
+ }
+
+ private static void println(
+ int level,
+ @NonNull String tag,
+ @NonNull String localTag,
+ @Nullable String msg,
+ @Nullable Object... args) {
+ // Formatted message is computed lazily if required.
+ String formattedMsg;
+ // Either null is passed as a single argument or more than one argument is passed.
+ boolean hasArgs = args == null || args.length > 0;
+ if ((level >= android.util.Log.INFO) || android.util.Log.isLoggable(tag, level)) {
+ formattedMsg = localTag;
+ if (!TextUtils.isEmpty(msg)) {
+ formattedMsg += SEPARATOR + (hasArgs ? String.format(msg, args) : msg);
+ }
+ android.util.Log.println(level, tag, formattedMsg);
+ }
+ }
+}
diff --git a/java/com/android/dialer/common/MathUtil.java b/java/com/android/dialer/common/MathUtil.java
new file mode 100644
index 000000000..e811a46e2
--- /dev/null
+++ b/java/com/android/dialer/common/MathUtil.java
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+/** Utility class for common math operations */
+public class MathUtil {
+
+ /**
+ * Interpolates between two integer values based on percentage.
+ *
+ * @param begin Begin value
+ * @param end End value
+ * @param percent Percentage value, between 0 and 1
+ * @return Interpolated result
+ */
+ public static int lerp(int begin, int end, float percent) {
+ return (int) (begin * (1 - percent) + end * percent);
+ }
+
+ /**
+ * Interpolates between two float values based on percentage.
+ *
+ * @param begin Begin value
+ * @param end End value
+ * @param percent Percentage value, between 0 and 1
+ * @return Interpolated result
+ */
+ public static float lerp(float begin, float end, float percent) {
+ return begin * (1 - percent) + end * percent;
+ }
+
+ /**
+ * Clamps a value between two bounds inclusively.
+ *
+ * @param value Value to be clamped
+ * @param min Lower bound
+ * @param max Upper bound
+ * @return Clamped value
+ */
+ public static float clamp(float value, float min, float max) {
+ return Math.max(min, Math.min(value, max));
+ }
+}
diff --git a/java/com/android/dialer/common/NetworkUtil.java b/java/com/android/dialer/common/NetworkUtil.java
new file mode 100644
index 000000000..47d84243e
--- /dev/null
+++ b/java/com/android/dialer/common/NetworkUtil.java
@@ -0,0 +1,192 @@
+/*
+ * 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.content.pm.PackageManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.support.annotation.Nullable;
+import android.support.annotation.RequiresPermission;
+import android.support.annotation.StringDef;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/** Utility class for dealing with network */
+public class NetworkUtil {
+
+ /* Returns the current network type. */
+ @RequiresPermission("android.permission.ACCESS_NETWORK_STATE")
+ @NetworkType
+ public static String getCurrentNetworkType(@Nullable Context context) {
+ if (context == null) {
+ return NetworkType.NONE;
+ }
+ ConnectivityManager connectivityManager =
+ (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ return getNetworkType(connectivityManager.getActiveNetworkInfo());
+ }
+
+ /* Returns the current network info. */
+ @Nullable
+ @RequiresPermission("android.permission.ACCESS_NETWORK_STATE")
+ public static NetworkInfo getCurrentNetworkInfo(@Nullable Context context) {
+ if (context == null) {
+ return null;
+ }
+ ConnectivityManager connectivityManager =
+ (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ return connectivityManager.getActiveNetworkInfo();
+ }
+
+ /**
+ * Returns the current network type as a string. For mobile network types the subtype name of the
+ * network is appended.
+ */
+ @RequiresPermission("android.permission.ACCESS_NETWORK_STATE")
+ public static String getCurrentNetworkTypeName(@Nullable Context context) {
+ if (context == null) {
+ return NetworkType.NONE;
+ }
+ ConnectivityManager connectivityManager =
+ (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
+ @NetworkType String networkType = getNetworkType(netInfo);
+ if (isNetworkTypeMobile(networkType)) {
+ return networkType + " (" + netInfo.getSubtypeName() + ")";
+ }
+ return networkType;
+ }
+
+ @NetworkType
+ public static String getNetworkType(@Nullable NetworkInfo netInfo) {
+ if (netInfo == null || !netInfo.isConnected()) {
+ return NetworkType.NONE;
+ }
+ switch (netInfo.getType()) {
+ case ConnectivityManager.TYPE_WIFI:
+ return NetworkType.WIFI;
+ case ConnectivityManager.TYPE_MOBILE:
+ return getMobileNetworkType(netInfo.getSubtype());
+ default:
+ return NetworkType.UNKNOWN;
+ }
+ }
+
+ public static boolean isNetworkTypeMobile(@NetworkType String networkType) {
+ return Objects.equals(networkType, NetworkType.MOBILE_2G)
+ || Objects.equals(networkType, NetworkType.MOBILE_3G)
+ || Objects.equals(networkType, NetworkType.MOBILE_4G);
+ }
+
+ @RequiresPermission("android.permission.ACCESS_NETWORK_STATE")
+ public static String getCurrentNetworkName(Context context) {
+ @NetworkType String networkType = getCurrentNetworkType(context);
+ switch (networkType) {
+ case NetworkType.WIFI:
+ return getWifiNetworkName(context);
+ case NetworkType.MOBILE_2G:
+ case NetworkType.MOBILE_3G:
+ case NetworkType.MOBILE_4G:
+ case NetworkType.MOBILE_UNKNOWN:
+ return getMobileNetworkName(context);
+ default:
+ return "";
+ }
+ }
+
+ private static String getWifiNetworkName(Context context) {
+ WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
+ String name = null;
+ if (context.checkSelfPermission("android.permission.ACCESS_WIFI_STATE")
+ == PackageManager.PERMISSION_GRANTED) {
+ //noinspection MissingPermission
+ WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
+ if (wifiInfo == null) {
+ return "";
+ }
+ name = wifiInfo.getSSID();
+ }
+ return TextUtils.isEmpty(name)
+ ? context.getString(R.string.network_name_wifi)
+ : name.replaceAll("\"", "");
+ }
+
+ private static String getMobileNetworkName(Context context) {
+ TelephonyManager telephonyMgr =
+ (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ String name = telephonyMgr.getNetworkOperatorName();
+ return TextUtils.isEmpty(name)
+ ? context.getString(R.string.network_name_mobile)
+ : name.replaceAll("\"", "");
+ }
+
+ @NetworkType
+ private static String getMobileNetworkType(int networkSubtype) {
+ switch (networkSubtype) {
+ case TelephonyManager.NETWORK_TYPE_1xRTT:
+ case TelephonyManager.NETWORK_TYPE_CDMA:
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ return NetworkType.MOBILE_2G;
+ case TelephonyManager.NETWORK_TYPE_EHRPD:
+ case TelephonyManager.NETWORK_TYPE_EVDO_0:
+ case TelephonyManager.NETWORK_TYPE_EVDO_A:
+ case TelephonyManager.NETWORK_TYPE_EVDO_B:
+ case TelephonyManager.NETWORK_TYPE_HSDPA:
+ case TelephonyManager.NETWORK_TYPE_HSPA:
+ case TelephonyManager.NETWORK_TYPE_HSPAP:
+ case TelephonyManager.NETWORK_TYPE_HSUPA:
+ case TelephonyManager.NETWORK_TYPE_UMTS:
+ return NetworkType.MOBILE_3G;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ return NetworkType.MOBILE_4G;
+ default:
+ return NetworkType.MOBILE_UNKNOWN;
+ }
+ }
+
+ /** Network types. */
+ @Retention(RetentionPolicy.SOURCE)
+ @StringDef(
+ value = {
+ NetworkType.NONE,
+ NetworkType.WIFI,
+ NetworkType.MOBILE_2G,
+ NetworkType.MOBILE_3G,
+ NetworkType.MOBILE_4G,
+ NetworkType.MOBILE_UNKNOWN,
+ NetworkType.UNKNOWN
+ }
+ )
+ public @interface NetworkType {
+
+ String NONE = "NONE";
+ String WIFI = "WIFI";
+ String MOBILE_2G = "MOBILE_2G";
+ String MOBILE_3G = "MOBILE_3G";
+ String MOBILE_4G = "MOBILE_4G";
+ String MOBILE_UNKNOWN = "MOBILE_UNKNOWN";
+ String UNKNOWN = "UNKNOWN";
+ }
+}
diff --git a/java/com/android/dialer/common/UiUtil.java b/java/com/android/dialer/common/UiUtil.java
new file mode 100644
index 000000000..4c4ebea11
--- /dev/null
+++ b/java/com/android/dialer/common/UiUtil.java
@@ -0,0 +1,41 @@
+/*
+ * 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.app.Activity;
+import android.content.Context;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+
+/** Utility class for commons functions used with Android UI. */
+public class UiUtil {
+
+ /** Hides the android keyboard. */
+ public static void hideKeyboardFrom(Context context, View view) {
+ InputMethodManager imm =
+ (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+ }
+
+ /** Opens the android keyboard. */
+ public static void openKeyboardFrom(Context context, View view) {
+ InputMethodManager inputMethodManager =
+ (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ inputMethodManager.toggleSoftInputFromWindow(
+ view.getApplicationWindowToken(), InputMethodManager.SHOW_FORCED, 0);
+ }
+}
diff --git a/java/com/android/dialer/common/res/values/strings.xml b/java/com/android/dialer/common/res/values/strings.xml
new file mode 100644
index 000000000..8e9616178
--- /dev/null
+++ b/java/com/android/dialer/common/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="network_name_wifi">Wifi</string>
+ <string name="network_name_mobile">Mobile</string>
+</resources>