summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assets/quantum/res/drawable/quantum_ic_delete_vd_theme_24.xml25
-rw-r--r--assets/quantum/res/drawable/quantum_ic_play_arrow_vd_theme_24.xml25
-rw-r--r--assets/quantum/res/drawable/quantum_ic_volume_up_vd_theme_24.xml25
-rw-r--r--java/com/android/dialer/app/AndroidManifest.xml1
-rw-r--r--java/com/android/dialer/app/DialtactsActivity.java30
-rw-r--r--java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java20
-rw-r--r--java/com/android/dialer/app/voicemail/LegacyVoicemailNotificationReceiver.java2
-rw-r--r--java/com/android/dialer/calllog/CallLogModule.java17
-rw-r--r--java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java8
-rw-r--r--java/com/android/dialer/calllog/datasources/DataSources.java6
-rw-r--r--java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java139
-rw-r--r--java/com/android/dialer/dialpadview/DialpadFragment.java2
-rw-r--r--java/com/android/dialer/dialpadview/res/layout/dialpad_fragment.xml1
-rw-r--r--java/com/android/dialer/phonelookup/testing/FakePhoneLookup.java83
-rw-r--r--java/com/android/dialer/precall/PreCallAction.java20
-rw-r--r--java/com/android/dialer/precall/PreCallCoordinator.java13
-rw-r--r--java/com/android/dialer/precall/impl/AssistedDialAction.java17
-rw-r--r--java/com/android/dialer/precall/impl/CallingAccountSelector.java23
-rw-r--r--java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java2
-rw-r--r--java/com/android/dialer/precall/impl/PreCallImpl.java20
-rw-r--r--java/com/android/dialer/preferredsim/impl/PreferredSimFallbackProvider.java1
-rw-r--r--java/com/android/dialer/searchfragment/common/QueryFilteringUtil.java2
-rw-r--r--java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java88
-rw-r--r--java/com/android/dialer/searchfragment/cp2/ContactTernarySearchTree.java97
-rw-r--r--java/com/android/dialer/searchfragment/list/NewSearchFragment.java5
-rw-r--r--java/com/android/dialer/telecom/TelecomUtil.java21
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java22
-rw-r--r--java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_media_player_layout.xml42
-rw-r--r--java/com/android/dialer/voicemail/listui/res/values/dimens.xml5
-rw-r--r--java/com/android/dialer/voicemail/listui/res/values/styles.xml25
-rw-r--r--java/com/android/dialer/voicemail/settings/VoicemailSettingsFragment.java29
-rw-r--r--java/com/android/dialer/widget/FloatingActionButtonController.java12
-rw-r--r--java/com/android/incallui/InCallActivity.java201
-rw-r--r--java/com/android/incallui/InCallActivityCommon.java279
-rw-r--r--java/com/android/incallui/InCallOrientationEventListener.java15
-rw-r--r--java/com/android/incallui/InCallPresenter.java61
-rw-r--r--java/com/android/incallui/bindings/InCallUiBindings.java4
-rw-r--r--java/com/android/incallui/bindings/InCallUiBindingsStub.java6
-rw-r--r--java/com/android/incallui/incall/impl/ButtonController.java6
-rw-r--r--java/com/android/incallui/incall/impl/CheckableLabeledButton.java10
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_00.pngbin0 -> 860 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_01.pngbin0 -> 942 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_02.pngbin0 -> 886 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_03.pngbin0 -> 822 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_04.pngbin0 -> 885 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_05.pngbin0 -> 915 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_06.pngbin0 -> 911 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_07.pngbin0 -> 907 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_08.pngbin0 -> 945 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_09.pngbin0 -> 917 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_10.pngbin0 -> 973 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_11.pngbin0 -> 950 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_12.pngbin0 -> 972 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_13.pngbin0 -> 940 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_14.pngbin0 -> 872 bytes
-rw-r--r--java/com/android/incallui/incall/impl/res/drawable/ic_sim_change_white.xml68
56 files changed, 1083 insertions, 395 deletions
diff --git a/assets/quantum/res/drawable/quantum_ic_delete_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_delete_vd_theme_24.xml
new file mode 100644
index 000000000..900b559e3
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_delete_vd_theme_24.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?attr/colorControlNormal"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
+</vector> \ No newline at end of file
diff --git a/assets/quantum/res/drawable/quantum_ic_play_arrow_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_play_arrow_vd_theme_24.xml
new file mode 100644
index 000000000..e17e625a5
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_play_arrow_vd_theme_24.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M8,5v14l11,-7z"/>
+</vector> \ No newline at end of file
diff --git a/assets/quantum/res/drawable/quantum_ic_volume_up_vd_theme_24.xml b/assets/quantum/res/drawable/quantum_ic_volume_up_vd_theme_24.xml
new file mode 100644
index 000000000..ac14beced
--- /dev/null
+++ b/assets/quantum/res/drawable/quantum_ic_volume_up_vd_theme_24.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?attr/colorControlNormal"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z"/>
+</vector> \ No newline at end of file
diff --git a/java/com/android/dialer/app/AndroidManifest.xml b/java/com/android/dialer/app/AndroidManifest.xml
index ad771496d..12abaa6a9 100644
--- a/java/com/android/dialer/app/AndroidManifest.xml
+++ b/java/com/android/dialer/app/AndroidManifest.xml
@@ -140,5 +140,6 @@
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
+ <meta-data android:name="supports_per_number_preferred_account" android:value="true" />
</application>
</manifest>
diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java
index 269e598e1..d9a63fab2 100644
--- a/java/com/android/dialer/app/DialtactsActivity.java
+++ b/java/com/android/dialer/app/DialtactsActivity.java
@@ -96,6 +96,7 @@ import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.callintent.CallSpecificAppData;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.UiUtil;
import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.configprovider.ConfigProviderBindings;
import com.android.dialer.constants.ActivityRequestCodes;
@@ -178,6 +179,7 @@ public class DialtactsActivity extends TransactionSafeActivity
private static final String KEY_IN_DIALPAD_SEARCH_UI = "in_dialpad_search_ui";
private static final String KEY_IN_NEW_SEARCH_UI = "in_new_search_ui";
private static final String KEY_SEARCH_QUERY = "search_query";
+ private static final String KEY_DIALPAD_QUERY = "dialpad_query";
private static final String KEY_FIRST_LAUNCH = "first_launch";
private static final String KEY_WAS_CONFIGURATION_CHANGE = "was_configuration_change";
private static final String KEY_IS_DIALPAD_SHOWN = "is_dialpad_shown";
@@ -439,6 +441,7 @@ public class DialtactsActivity extends TransactionSafeActivity
.commit();
} else {
mSearchQuery = savedInstanceState.getString(KEY_SEARCH_QUERY);
+ mDialpadQuery = savedInstanceState.getString(KEY_DIALPAD_QUERY);
mInRegularSearch = savedInstanceState.getBoolean(KEY_IN_REGULAR_SEARCH_UI);
mInDialpadSearch = savedInstanceState.getBoolean(KEY_IN_DIALPAD_SEARCH_UI);
mInNewSearch = savedInstanceState.getBoolean(KEY_IN_NEW_SEARCH_UI);
@@ -654,6 +657,7 @@ public class DialtactsActivity extends TransactionSafeActivity
LogUtil.enterBlock("DialtactsActivity.onSaveInstanceState");
super.onSaveInstanceState(outState);
outState.putString(KEY_SEARCH_QUERY, mSearchQuery);
+ outState.putString(KEY_DIALPAD_QUERY, mDialpadQuery);
outState.putBoolean(KEY_IN_REGULAR_SEARCH_UI, mInRegularSearch);
outState.putBoolean(KEY_IN_DIALPAD_SEARCH_UI, mInDialpadSearch);
outState.putBoolean(KEY_IN_NEW_SEARCH_UI, mInNewSearch);
@@ -1425,6 +1429,21 @@ public class DialtactsActivity extends TransactionSafeActivity
}
@Override
+ public boolean onSearchListTouch(MotionEvent event) {
+ if (mIsDialpadShown) {
+ PerformanceReport.recordClick(UiAction.Type.CLOSE_DIALPAD);
+ hideDialpadFragment(true, false);
+ if (TextUtils.isEmpty(mDialpadQuery)) {
+ exitSearchUi();
+ }
+ return true;
+ } else {
+ UiUtil.hideKeyboardFrom(this, mSearchEditTextLayout);
+ }
+ return false;
+ }
+
+ @Override
public void onListFragmentScrollStateChange(int scrollState) {
PerformanceReport.recordScrollStateChange(scrollState);
if (scrollState == OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
@@ -1659,17 +1678,6 @@ public class DialtactsActivity extends TransactionSafeActivity
}
@Override
- public boolean onSearchListTouch(MotionEvent event) {
- if (mIsDialpadShown) {
- hideDialpadFragment(true, false);
- if (TextUtils.isEmpty(mDialpadQuery)) {
- exitSearchUi();
- }
- }
- return false;
- }
-
- @Override
public void onCallPlaced() {
if (mIsDialpadShown) {
hideDialpadFragment(false, true);
diff --git a/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java b/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java
index 584f07fe3..a0bbfa0f1 100644
--- a/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java
+++ b/java/com/android/dialer/app/calllog/LegacyVoicemailNotifier.java
@@ -40,6 +40,7 @@ import com.android.dialer.notification.NotificationChannelManager;
/** Shows a notification in the status bar for legacy vociemail. */
@TargetApi(VERSION_CODES.O)
public final class LegacyVoicemailNotifier {
+ private static final String NOTIFICATION_TAG_PREFIX = "LegacyVoicemail_";
private static final String NOTIFICATION_TAG = "LegacyVoicemail";
private static final int NOTIFICATION_ID = 1;
@@ -77,7 +78,8 @@ public final class LegacyVoicemailNotifier {
callVoicemailIntent,
voicemailSettingsIntent,
isRefresh);
- DialerNotificationManager.notify(context, NOTIFICATION_TAG, NOTIFICATION_ID, notification);
+ DialerNotificationManager.notify(
+ context, getNotificationTag(context, handle), NOTIFICATION_ID, notification);
}
@NonNull
@@ -146,10 +148,22 @@ public final class LegacyVoicemailNotifier {
}
}
- public static void cancelNotification(@NonNull Context context) {
+ public static void cancelNotification(
+ @NonNull Context context, @NonNull PhoneAccountHandle phoneAccountHandle) {
LogUtil.enterBlock("LegacyVoicemailNotifier.cancelNotification");
Assert.checkArgument(BuildCompat.isAtLeastO());
- DialerNotificationManager.cancel(context, NOTIFICATION_TAG, NOTIFICATION_ID);
+ Assert.isNotNull(phoneAccountHandle);
+ DialerNotificationManager.cancel(
+ context, getNotificationTag(context, phoneAccountHandle), NOTIFICATION_ID);
+ }
+
+ @NonNull
+ private static String getNotificationTag(
+ @NonNull Context context, @NonNull PhoneAccountHandle phoneAccountHandle) {
+ if (context.getSystemService(TelephonyManager.class).getPhoneCount() <= 1) {
+ return NOTIFICATION_TAG;
+ }
+ return NOTIFICATION_TAG_PREFIX + phoneAccountHandle.getId();
}
private LegacyVoicemailNotifier() {}
diff --git a/java/com/android/dialer/app/voicemail/LegacyVoicemailNotificationReceiver.java b/java/com/android/dialer/app/voicemail/LegacyVoicemailNotificationReceiver.java
index 3ce837b8c..fee845469 100644
--- a/java/com/android/dialer/app/voicemail/LegacyVoicemailNotificationReceiver.java
+++ b/java/com/android/dialer/app/voicemail/LegacyVoicemailNotificationReceiver.java
@@ -96,7 +96,7 @@ public class LegacyVoicemailNotificationReceiver extends BroadcastReceiver {
if (count == 0) {
LogUtil.i("LegacyVoicemailNotificationReceiver.onReceive", "clearing notification");
- LegacyVoicemailNotifier.cancelNotification(context);
+ LegacyVoicemailNotifier.cancelNotification(context, phoneAccountHandle);
return;
}
diff --git a/java/com/android/dialer/calllog/CallLogModule.java b/java/com/android/dialer/calllog/CallLogModule.java
index 2f2f16d5b..9926cebb9 100644
--- a/java/com/android/dialer/calllog/CallLogModule.java
+++ b/java/com/android/dialer/calllog/CallLogModule.java
@@ -19,12 +19,11 @@ package com.android.dialer.calllog;
import com.android.dialer.calllog.datasources.CallLogDataSource;
import com.android.dialer.calllog.datasources.DataSources;
import com.android.dialer.calllog.datasources.contacts.ContactsDataSource;
+import com.android.dialer.calllog.datasources.phonelookup.PhoneLookupDataSource;
import com.android.dialer.calllog.datasources.systemcalllog.SystemCallLogDataSource;
+import com.google.common.collect.ImmutableList;
import dagger.Module;
import dagger.Provides;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
/** Dagger module which satisfies call log dependencies. */
@Module
@@ -32,10 +31,12 @@ public abstract class CallLogModule {
@Provides
static DataSources provideCallLogDataSources(
- SystemCallLogDataSource systemCallLogDataSource, ContactsDataSource contactsDataSource) {
+ SystemCallLogDataSource systemCallLogDataSource,
+ ContactsDataSource contactsDataSource,
+ PhoneLookupDataSource phoneLookupDataSource) {
// System call log must be first, see getDataSourcesExcludingSystemCallLog below.
- List<CallLogDataSource> allDataSources =
- Collections.unmodifiableList(Arrays.asList(systemCallLogDataSource, contactsDataSource));
+ ImmutableList<CallLogDataSource> allDataSources =
+ ImmutableList.of(systemCallLogDataSource, contactsDataSource, phoneLookupDataSource);
return new DataSources() {
@Override
public SystemCallLogDataSource getSystemCallLogDataSource() {
@@ -43,12 +44,12 @@ public abstract class CallLogModule {
}
@Override
- public List<CallLogDataSource> getDataSourcesIncludingSystemCallLog() {
+ public ImmutableList<CallLogDataSource> getDataSourcesIncludingSystemCallLog() {
return allDataSources;
}
@Override
- public List<CallLogDataSource> getDataSourcesExcludingSystemCallLog() {
+ public ImmutableList<CallLogDataSource> getDataSourcesExcludingSystemCallLog() {
return allDataSources.subList(1, allDataSources.size());
}
};
diff --git a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
index 3062710d4..0d8e8ceeb 100644
--- a/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
+++ b/java/com/android/dialer/calllog/database/AnnotatedCallLogDatabaseHelper.java
@@ -89,6 +89,13 @@ class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper {
+ AnnotatedCallLog.CALL_TYPE
+ ");";
+ private static final String CREATE_INDEX_ON_NUMBER_SQL =
+ "create index number_index on "
+ + AnnotatedCallLog.TABLE
+ + " ("
+ + AnnotatedCallLog.NUMBER
+ + ");";
+
@Override
public void onCreate(SQLiteDatabase db) {
LogUtil.enterBlock("AnnotatedCallLogDatabaseHelper.onCreate");
@@ -96,6 +103,7 @@ class AnnotatedCallLogDatabaseHelper extends SQLiteOpenHelper {
db.execSQL(CREATE_TABLE_SQL);
db.execSQL(String.format(Locale.US, CREATE_TRIGGER_SQL, maxRows, maxRows));
db.execSQL(CREATE_INDEX_ON_CALL_TYPE_SQL);
+ db.execSQL(CREATE_INDEX_ON_NUMBER_SQL);
// TODO(zachh): Consider logging impression.
LogUtil.i(
"AnnotatedCallLogDatabaseHelper.onCreate",
diff --git a/java/com/android/dialer/calllog/datasources/DataSources.java b/java/com/android/dialer/calllog/datasources/DataSources.java
index 911ca3fa3..113a9f7b1 100644
--- a/java/com/android/dialer/calllog/datasources/DataSources.java
+++ b/java/com/android/dialer/calllog/datasources/DataSources.java
@@ -17,14 +17,14 @@
package com.android.dialer.calllog.datasources;
import com.android.dialer.calllog.datasources.systemcalllog.SystemCallLogDataSource;
-import java.util.List;
+import com.google.common.collect.ImmutableList;
/** Immutable lists of data sources used to populate the annotated call log. */
public interface DataSources {
SystemCallLogDataSource getSystemCallLogDataSource();
- List<CallLogDataSource> getDataSourcesIncludingSystemCallLog();
+ ImmutableList<CallLogDataSource> getDataSourcesIncludingSystemCallLog();
- List<CallLogDataSource> getDataSourcesExcludingSystemCallLog();
+ ImmutableList<CallLogDataSource> getDataSourcesExcludingSystemCallLog();
}
diff --git a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java
new file mode 100644
index 000000000..90298a104
--- /dev/null
+++ b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java
@@ -0,0 +1,139 @@
+/*
+ * 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.calllog.datasources.phonelookup;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.database.Cursor;
+import android.support.annotation.MainThread;
+import android.support.annotation.WorkerThread;
+import com.android.dialer.DialerPhoneNumber;
+import com.android.dialer.calllog.database.contract.AnnotatedCallLogContract.AnnotatedCallLog;
+import com.android.dialer.calllog.datasources.CallLogDataSource;
+import com.android.dialer.calllog.datasources.CallLogMutations;
+import com.android.dialer.common.LogUtil;
+import com.android.dialer.phonelookup.PhoneLookup;
+import com.android.dialer.storage.Unencrypted;
+import com.google.common.collect.ImmutableSet;
+import com.google.protobuf.InvalidProtocolBufferException;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import javax.inject.Inject;
+
+/**
+ * Responsible for maintaining the columns in the annotated call log which are derived from phone
+ * numbers.
+ */
+public final class PhoneLookupDataSource implements CallLogDataSource {
+ private static final String PREF_LAST_TIMESTAMP_PROCESSED = "phoneLookupLastTimestampProcessed";
+
+ private final PhoneLookup phoneLookup;
+ private final SharedPreferences sharedPreferences;
+
+ @Inject
+ PhoneLookupDataSource(PhoneLookup phoneLookup, @Unencrypted SharedPreferences sharedPreferences) {
+ this.phoneLookup = phoneLookup;
+ this.sharedPreferences = sharedPreferences;
+ }
+
+ @WorkerThread
+ @Override
+ public boolean isDirty(Context appContext) {
+ ImmutableSet<DialerPhoneNumber> uniqueDialerPhoneNumbers =
+ queryDistinctDialerPhoneNumbersFromAnnotatedCallLog(appContext);
+
+ long lastTimestampProcessedSharedPrefValue =
+ sharedPreferences.getLong(PREF_LAST_TIMESTAMP_PROCESSED, 0L);
+ try {
+ // TODO(zachh): Would be good to rework call log architecture to properly use futures.
+ // TODO(zachh): Consider how individual lookups should behave wrt timeouts/exceptions and
+ // handle appropriately here.
+ return phoneLookup
+ .isDirty(uniqueDialerPhoneNumbers, lastTimestampProcessedSharedPrefValue)
+ .get();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @WorkerThread
+ @Override
+ public void fill(Context appContext, CallLogMutations mutations) {
+ // TODO(zachh): Implementation.
+ }
+
+ @WorkerThread
+ @Override
+ public void onSuccessfulFill(Context appContext) {
+ // TODO(zachh): Implementation.
+ }
+
+ @WorkerThread
+ @Override
+ public ContentValues coalesce(List<ContentValues> individualRowsSortedByTimestampDesc) {
+ // TODO(zachh): Implementation.
+ return new ContentValues();
+ }
+
+ @MainThread
+ @Override
+ public void registerContentObservers(
+ Context appContext, ContentObserverCallbacks contentObserverCallbacks) {
+ // No content observers required for this data source.
+ }
+
+ private static ImmutableSet<DialerPhoneNumber>
+ queryDistinctDialerPhoneNumbersFromAnnotatedCallLog(Context appContext) {
+ ImmutableSet.Builder<DialerPhoneNumber> numbers = ImmutableSet.builder();
+
+ try (Cursor cursor =
+ appContext
+ .getContentResolver()
+ .query(
+ AnnotatedCallLog.DISTINCT_NUMBERS_CONTENT_URI,
+ new String[] {AnnotatedCallLog.NUMBER},
+ null,
+ null,
+ null)) {
+
+ if (cursor == null) {
+ LogUtil.e(
+ "PhoneLookupDataSource.queryDistinctDialerPhoneNumbersFromAnnotatedCallLog",
+ "null cursor");
+ return numbers.build();
+ }
+
+ if (cursor.moveToFirst()) {
+ int numberColumn = cursor.getColumnIndexOrThrow(AnnotatedCallLog.NUMBER);
+ do {
+ byte[] blob = cursor.getBlob(numberColumn);
+ if (blob == null) {
+ // Not all [incoming] calls have associated phone numbers.
+ continue;
+ }
+ try {
+ numbers.add(DialerPhoneNumber.parseFrom(blob));
+ } catch (InvalidProtocolBufferException e) {
+ throw new IllegalStateException(e);
+ }
+ } while (cursor.moveToNext());
+ }
+ }
+ return numbers.build();
+ }
+}
diff --git a/java/com/android/dialer/dialpadview/DialpadFragment.java b/java/com/android/dialer/dialpadview/DialpadFragment.java
index e85b57e33..8d11bcbe3 100644
--- a/java/com/android/dialer/dialpadview/DialpadFragment.java
+++ b/java/com/android/dialer/dialpadview/DialpadFragment.java
@@ -643,7 +643,7 @@ public class DialpadFragment extends Fragment
iconId = R.drawable.ic_wifi_calling;
}
mFloatingActionButtonController.changeIcon(
- res.getDrawable(iconId, null), res.getString(R.string.description_dial_button));
+ iconId, res.getString(R.string.description_dial_button));
mDialpadQueryListener =
FragmentUtils.getParentUnsafe(this, OnDialpadQueryChangedListener.class);
diff --git a/java/com/android/dialer/dialpadview/res/layout/dialpad_fragment.xml b/java/com/android/dialer/dialpadview/res/layout/dialpad_fragment.xml
index 2f62e1407..2e6b6eca0 100644
--- a/java/com/android/dialer/dialpadview/res/layout/dialpad_fragment.xml
+++ b/java/com/android/dialer/dialpadview/res/layout/dialpad_fragment.xml
@@ -66,6 +66,7 @@
android:layout_centerHorizontal="true"
android:contentDescription="@string/description_dial_button"
android:src="@drawable/quantum_ic_call_vd_theme_24"
+ android:tint="#ffffff"
app:backgroundTint="@color/dialpad_fab_green"
app:colorControlNormal="#ffffff"
app:elevation="@dimen/floating_action_button_translation_z"/>
diff --git a/java/com/android/dialer/phonelookup/testing/FakePhoneLookup.java b/java/com/android/dialer/phonelookup/testing/FakePhoneLookup.java
new file mode 100644
index 000000000..853116f9a
--- /dev/null
+++ b/java/com/android/dialer/phonelookup/testing/FakePhoneLookup.java
@@ -0,0 +1,83 @@
+/*
+ * 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.phonelookup.testing;
+
+import android.support.annotation.NonNull;
+import android.telecom.Call;
+import com.android.dialer.DialerPhoneNumber;
+import com.android.dialer.phonelookup.PhoneLookup;
+import com.android.dialer.phonelookup.PhoneLookupInfo;
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+/** Fake implementation of {@link PhoneLookup} used for unit tests. */
+@AutoValue
+public abstract class FakePhoneLookup implements PhoneLookup {
+
+ abstract PhoneLookupInfo lookupResult();
+
+ abstract ImmutableMap<DialerPhoneNumber, PhoneLookupInfo> bulkUpdateResult();
+
+ abstract boolean isDirtyResult();
+
+ public static Builder builder() {
+ return new AutoValue_FakePhoneLookup.Builder()
+ .setLookupResult(PhoneLookupInfo.getDefaultInstance())
+ .setBulkUpdateResult(ImmutableMap.of())
+ .setIsDirtyResult(false);
+ }
+
+ /** Builder. */
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract Builder setLookupResult(PhoneLookupInfo phoneLookupInfo);
+
+ public abstract Builder setBulkUpdateResult(
+ ImmutableMap<DialerPhoneNumber, PhoneLookupInfo> map);
+
+ public abstract Builder setIsDirtyResult(boolean isDirty);
+
+ public abstract FakePhoneLookup build();
+ }
+
+ @Override
+ public ListenableFuture<PhoneLookupInfo> lookup(@NonNull Call call) {
+ SettableFuture<PhoneLookupInfo> future = SettableFuture.create();
+ future.set(lookupResult());
+ return future;
+ }
+
+ @Override
+ public ListenableFuture<Boolean> isDirty(
+ ImmutableSet<DialerPhoneNumber> phoneNumbers, long lastModified) {
+ SettableFuture<Boolean> future = SettableFuture.create();
+ future.set(isDirtyResult());
+ return future;
+ }
+
+ @Override
+ public ListenableFuture<ImmutableMap<DialerPhoneNumber, PhoneLookupInfo>> bulkUpdate(
+ ImmutableMap<DialerPhoneNumber, PhoneLookupInfo> existingInfoMap, long lastModified) {
+ SettableFuture<ImmutableMap<DialerPhoneNumber, PhoneLookupInfo>> future =
+ SettableFuture.create();
+ future.set(bulkUpdateResult());
+ return future;
+ }
+}
diff --git a/java/com/android/dialer/precall/PreCallAction.java b/java/com/android/dialer/precall/PreCallAction.java
index 9434694a4..9ddc6f205 100644
--- a/java/com/android/dialer/precall/PreCallAction.java
+++ b/java/com/android/dialer/precall/PreCallAction.java
@@ -16,6 +16,7 @@
package com.android.dialer.precall;
+import android.content.Context;
import android.support.annotation.MainThread;
import com.android.dialer.callintent.CallIntentBuilder;
@@ -28,12 +29,29 @@ import com.android.dialer.callintent.CallIntentBuilder;
public interface PreCallAction {
/**
+ * Whether the action requires an activity to operate. This method is called on all actions before
+ * {@link #runWithUi(PreCallCoordinator)} is called. If {@link true} is returned, {@link
+ * #runWithUi(PreCallCoordinator)} will be guaranteed to be called on the execution phase.
+ * Otherwise {@link #runWithoutUi(Context, CallIntentBuilder)} may be called instead and the
+ * action will not be able to show UI, perform async task, or abort the call. This method should
+ * not make any state changes.
+ */
+ @MainThread
+ boolean requiresUi(Context context, CallIntentBuilder builder);
+
+ /**
+ * Called when all actions returned {@code false} for {@link #requiresUi(Context,
+ * CallIntentBuilder)}.
+ */
+ void runWithoutUi(Context context, CallIntentBuilder builder);
+
+ /**
* Runs the action. Should block on the main thread until the action is finished. If the action is
* not instantaneous, {@link PreCallCoordinator#startPendingAction()} should be called to release
* the thread and continue later.
*/
@MainThread
- void run(PreCallCoordinator coordinator);
+ void runWithUi(PreCallCoordinator coordinator);
/**
* Called when the UI is being paused when a {@link PreCallCoordinator.PendingAction} is started,
diff --git a/java/com/android/dialer/precall/PreCallCoordinator.java b/java/com/android/dialer/precall/PreCallCoordinator.java
index 40b909a51..cb3221afd 100644
--- a/java/com/android/dialer/precall/PreCallCoordinator.java
+++ b/java/com/android/dialer/precall/PreCallCoordinator.java
@@ -33,10 +33,7 @@ public interface PreCallCoordinator {
@NonNull
CallIntentBuilder getBuilder();
- /**
- * @return the activity to attach the UI to. Returns {@link null} if the coordinator is running on
- * headless mode. TODO(twyen): implement headless mode.
- */
+ /** @return the activity to attach the UI to. */
@NonNull
Activity getActivity();
@@ -60,10 +57,10 @@ public interface PreCallCoordinator {
* Called by the current running {@link PreCallAction} to release the main thread and resume
* pre-call later.
*
- * @return a {@link PendingAction} which {@link PendingAction#finish(boolean)} should be called to
- * resume pre-call. For example the action shows a dialog to the user, startPendingAction()
- * should be called as the action will not be finished immediately. When the dialog is
- * completed, {@code finish()} is then called to continue the next step.
+ * @return a {@link PendingAction} which {@link PendingAction#finish()} should be called to resume
+ * pre-call. For example the action shows a dialog to the user, startPendingAction() should be
+ * called as the action will not be finished immediately. When the dialog is completed, {@code
+ * finish()} is then called to continue the next step.
*/
@MainThread
@NonNull
diff --git a/java/com/android/dialer/precall/impl/AssistedDialAction.java b/java/com/android/dialer/precall/impl/AssistedDialAction.java
index edf97cce3..c4f61d2dd 100644
--- a/java/com/android/dialer/precall/impl/AssistedDialAction.java
+++ b/java/com/android/dialer/precall/impl/AssistedDialAction.java
@@ -17,6 +17,7 @@
package com.android.dialer.precall.impl;
import android.annotation.TargetApi;
+import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.telecom.PhoneAccount;
@@ -35,18 +36,21 @@ import java.util.Optional;
/** Rewrites the call URI with country code. TODO(erfanian): use phone account for multi SIM */
public class AssistedDialAction implements PreCallAction {
+ @Override
+ public boolean requiresUi(Context context, CallIntentBuilder builder) {
+ return false;
+ }
+
@SuppressWarnings("AndroidApiChecker") // Use of optional
@TargetApi(Build.VERSION_CODES.N)
@Override
- public void run(PreCallCoordinator coordinator) {
- CallIntentBuilder builder = coordinator.getBuilder();
+ public void runWithoutUi(Context context, CallIntentBuilder builder) {
if (!builder.isAssistedDialAllowed()) {
return;
}
AssistedDialingMediator assistedDialingMediator =
ConcreteCreator.createNewAssistedDialingMediator(
- coordinator.getActivity().getSystemService(TelephonyManager.class),
- coordinator.getActivity());
+ context.getSystemService(TelephonyManager.class), context);
if (!assistedDialingMediator.isPlatformEligible()) {
return;
}
@@ -69,5 +73,10 @@ public class AssistedDialAction implements PreCallAction {
}
@Override
+ public void runWithUi(PreCallCoordinator coordinator) {
+ runWithoutUi(coordinator.getActivity(), coordinator.getBuilder());
+ }
+
+ @Override
public void onDiscard() {}
}
diff --git a/java/com/android/dialer/precall/impl/CallingAccountSelector.java b/java/com/android/dialer/precall/impl/CallingAccountSelector.java
index ca74bef08..d763c7a5f 100644
--- a/java/com/android/dialer/precall/impl/CallingAccountSelector.java
+++ b/java/com/android/dialer/precall/impl/CallingAccountSelector.java
@@ -59,16 +59,27 @@ public class CallingAccountSelector implements PreCallAction {
private boolean isDiscarding;
@Override
- @MainThread
- public void run(PreCallCoordinator coordinator) {
- CallIntentBuilder builder = coordinator.getBuilder();
+ public boolean requiresUi(Context context, CallIntentBuilder builder) {
if (builder.getPhoneAccountHandle() != null) {
- return;
+ return false;
}
- Activity activity = coordinator.getActivity();
- TelecomManager telecomManager = activity.getSystemService(TelecomManager.class);
+ TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
List<PhoneAccountHandle> accounts = telecomManager.getCallCapablePhoneAccounts();
if (accounts.size() <= 1) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void runWithoutUi(Context context, CallIntentBuilder builder) {
+ // do nothing.
+ }
+
+ @Override
+ public void runWithUi(PreCallCoordinator coordinator) {
+ CallIntentBuilder builder = coordinator.getBuilder();
+ if (!requiresUi(coordinator.getActivity(), builder)) {
return;
}
switch (builder.getUri().getScheme()) {
diff --git a/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java b/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java
index 6302a2395..485823e9a 100644
--- a/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java
+++ b/java/com/android/dialer/precall/impl/PreCallCoordinatorImpl.java
@@ -93,7 +93,7 @@ public class PreCallCoordinatorImpl implements PreCallCoordinator {
}
LogUtil.i("PreCallCoordinatorImpl.runNextAction", "running " + actions.get(currentActionIndex));
currentAction = actions.get(currentActionIndex);
- actions.get(currentActionIndex).run(this);
+ actions.get(currentActionIndex).runWithUi(this);
if (pendingAction == null) {
onActionFinished();
}
diff --git a/java/com/android/dialer/precall/impl/PreCallImpl.java b/java/com/android/dialer/precall/impl/PreCallImpl.java
index 21c5dc9e2..1c78bb8b0 100644
--- a/java/com/android/dialer/precall/impl/PreCallImpl.java
+++ b/java/com/android/dialer/precall/impl/PreCallImpl.java
@@ -20,8 +20,10 @@ import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
import com.android.dialer.callintent.CallIntentBuilder;
+import com.android.dialer.common.LogUtil;
import com.android.dialer.precall.PreCall;
import com.android.dialer.precall.PreCallAction;
+import com.android.dialer.precall.PreCallComponent;
import com.android.dialer.precall.PreCallCoordinator;
import com.google.common.collect.ImmutableList;
import javax.inject.Inject;
@@ -40,8 +42,26 @@ public class PreCallImpl implements PreCall {
@NonNull
@Override
public Intent buildIntent(Context context, CallIntentBuilder builder) {
+ if (!requiresUi(context, builder)) {
+ LogUtil.i("PreCallImpl.buildIntent", "No UI requested, running pre-call directly");
+ for (PreCallAction action : PreCallComponent.get(context).getPreCall().getActions()) {
+ action.runWithoutUi(context, builder);
+ }
+ return builder.build();
+ }
+ LogUtil.i("PreCallImpl.buildIntent", "building intent to start activity");
Intent intent = new Intent(context, PreCallActivity.class);
intent.putExtra(PreCallCoordinator.EXTRA_CALL_INTENT_BUILDER, builder);
return intent;
}
+
+ private boolean requiresUi(Context context, CallIntentBuilder builder) {
+ for (PreCallAction action : PreCallComponent.get(context).getPreCall().getActions()) {
+ if (action.requiresUi(context, builder)) {
+ LogUtil.i("PreCallImpl.requiresUi", action + " requested UI");
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/java/com/android/dialer/preferredsim/impl/PreferredSimFallbackProvider.java b/java/com/android/dialer/preferredsim/impl/PreferredSimFallbackProvider.java
index 322baa2ef..1b10765a5 100644
--- a/java/com/android/dialer/preferredsim/impl/PreferredSimFallbackProvider.java
+++ b/java/com/android/dialer/preferredsim/impl/PreferredSimFallbackProvider.java
@@ -131,6 +131,7 @@ public class PreferredSimFallbackProvider extends ContentProvider {
== -1) {
throw new IllegalStateException("update failed");
}
+ getContext().getContentResolver().notifyChange(PreferredSimFallbackContract.CONTENT_URI, null);
return 1;
}
diff --git a/java/com/android/dialer/searchfragment/common/QueryFilteringUtil.java b/java/com/android/dialer/searchfragment/common/QueryFilteringUtil.java
index 1ecb486d2..c4ff27545 100644
--- a/java/com/android/dialer/searchfragment/common/QueryFilteringUtil.java
+++ b/java/com/android/dialer/searchfragment/common/QueryFilteringUtil.java
@@ -137,7 +137,7 @@ public class QueryFilteringUtil {
* @param context The context
* @return The original string with characters replaced with T9 representations.
*/
- static String getT9Representation(String s, Context context) {
+ public static String getT9Representation(String s, Context context) {
StringBuilder builder = new StringBuilder(s.length());
for (char c : s.toLowerCase().toCharArray()) {
builder.append(getDigit(c, context));
diff --git a/java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java b/java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java
index 166902b2b..dc16f9dd0 100644
--- a/java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java
+++ b/java/com/android/dialer/searchfragment/cp2/ContactFilterCursor.java
@@ -39,6 +39,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
/**
@@ -52,6 +53,7 @@ final class ContactFilterCursor implements Cursor {
private final Cursor cursor;
// List of cursor ids that are valid for displaying after filtering.
private final List<Integer> queryFilteredPositions = new ArrayList<>();
+ private final ContactTernarySearchTree contactTree;
private int currentPosition = 0;
@@ -77,6 +79,7 @@ final class ContactFilterCursor implements Cursor {
*/
ContactFilterCursor(Cursor cursor, @Nullable String query, Context context) {
this.cursor = createCursor(cursor);
+ contactTree = buildContactSearchTree(context, this.cursor);
filter(query, context);
}
@@ -225,6 +228,69 @@ final class ContactFilterCursor implements Cursor {
}
/**
+ * Returns a ternary search trie based on the contact at the cursor's current position with the
+ * following terms inserted:
+ *
+ * <ul>
+ * <li>Contact's whole display name, company name and nickname.
+ * <li>The T9 representations of those values
+ * <li>The T9 initials of those values
+ * <li>All possible substrings a contact's phone number
+ * </ul>
+ */
+ private static ContactTernarySearchTree buildContactSearchTree(Context context, Cursor cursor) {
+ ContactTernarySearchTree tree = new ContactTernarySearchTree();
+ cursor.moveToPosition(-1);
+ while (cursor.moveToNext()) {
+ int position = cursor.getPosition();
+ Set<String> queryMatches = new ArraySet<>();
+ addMatches(context, queryMatches, cursor.getString(Projections.DISPLAY_NAME));
+ addMatches(context, queryMatches, cursor.getString(Projections.COMPANY_NAME));
+ addMatches(context, queryMatches, cursor.getString(Projections.NICKNAME));
+ for (String query : queryMatches) {
+ tree.put(query, position);
+ }
+ String number = QueryFilteringUtil.digitsOnly(cursor.getString(Projections.PHONE_NUMBER));
+ Set<String> numberSubstrings = new ArraySet<>();
+ numberSubstrings.add(number);
+ for (int start = 0; start < number.length(); start++) {
+ numberSubstrings.add(number.substring(start, number.length()));
+ }
+ for (String substring : numberSubstrings) {
+ tree.put(substring, position);
+ }
+ }
+ return tree;
+ }
+
+ /**
+ * Returns a set containing:
+ *
+ * <ul>
+ * <li>The white space divided parts of phrase
+ * <li>The T9 representation of the white space divided parts of phrase
+ * <li>The T9 representation of the initials (i.e. first character of each part) of phrase
+ * </ul>
+ */
+ private static void addMatches(Context context, Set<String> existingMatches, String phrase) {
+ if (TextUtils.isEmpty(phrase)) {
+ return;
+ }
+ String initials = "";
+ phrase = phrase.toLowerCase(Locale.getDefault());
+ existingMatches.add(phrase);
+ for (String name : phrase.split("\\s")) {
+ if (TextUtils.isEmpty(name)) {
+ continue;
+ }
+ existingMatches.add(name);
+ existingMatches.add(QueryFilteringUtil.getT9Representation(name, context));
+ initials += name.charAt(0);
+ }
+ existingMatches.add(QueryFilteringUtil.getT9Representation(initials, context));
+ }
+
+ /**
* Filters out contacts that do not match the query.
*
* <p>The query can have at least 1 of 3 forms:
@@ -249,24 +315,14 @@ final class ContactFilterCursor implements Cursor {
query = "";
}
queryFilteredPositions.clear();
- query = query.toLowerCase();
- cursor.moveToPosition(-1);
-
- while (cursor.moveToNext()) {
- int position = cursor.getPosition();
- String number = cursor.getString(Projections.PHONE_NUMBER);
- String name = cursor.getString(Projections.DISPLAY_NAME);
- String companyName = cursor.getString(Projections.COMPANY_NAME);
- String nickName = cursor.getString(Projections.NICKNAME);
- if (TextUtils.isEmpty(query)
- || QueryFilteringUtil.nameMatchesT9Query(query, name, context)
- || QueryFilteringUtil.numberMatchesNumberQuery(query, number)
- || QueryFilteringUtil.nameContainsQuery(query, name)
- || QueryFilteringUtil.nameContainsQuery(query, companyName)
- || QueryFilteringUtil.nameContainsQuery(query, nickName)) {
- queryFilteredPositions.add(position);
+ if (TextUtils.isEmpty(query)) {
+ for (int i = 0; i < cursor.getCount(); i++) {
+ queryFilteredPositions.add(i);
}
+ } else {
+ queryFilteredPositions.addAll(contactTree.get(query.toLowerCase(Locale.getDefault())));
}
+ Collections.sort(queryFilteredPositions);
currentPosition = 0;
cursor.moveToFirst();
}
diff --git a/java/com/android/dialer/searchfragment/cp2/ContactTernarySearchTree.java b/java/com/android/dialer/searchfragment/cp2/ContactTernarySearchTree.java
new file mode 100644
index 000000000..88738e281
--- /dev/null
+++ b/java/com/android/dialer/searchfragment/cp2/ContactTernarySearchTree.java
@@ -0,0 +1,97 @@
+/*
+ * 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.searchfragment.cp2;
+
+import android.support.v4.util.ArraySet;
+import android.text.TextUtils;
+import java.util.Set;
+
+/** Ternary Search Tree for searching a list of contacts. */
+public class ContactTernarySearchTree {
+
+ private Node root;
+
+ /**
+ * Add {@code value} to all middle and end {@link Node#values} that correspond to {@code key}.
+ *
+ * <p>For example, if {@code key} were "FOO", {@code value} would be added to nodes "F", "O" and
+ * "O". But if the traversal required visiting {@link Node#left} or {@link Node#right}, {@code
+ * value} wouldn't be added to those nodes.
+ */
+ public void put(String key, int value) {
+ if (TextUtils.isEmpty(key)) {
+ return;
+ }
+ root = put(root, key, value, 0);
+ }
+
+ private Node put(Node node, String key, int value, int position) {
+ char c = key.charAt(position);
+ if (node == null) {
+ node = new Node();
+ node.key = c;
+ }
+ if (c < node.key) {
+ node.left = put(node.left, key, value, position);
+ } else if (c > node.key) {
+ node.right = put(node.right, key, value, position);
+ } else if (position < key.length() - 1) {
+ node.values.add(value);
+ node.mid = put(node.mid, key, value, position + 1);
+ } else {
+ node.values.add(value);
+ }
+ return node;
+ }
+
+ /** Returns true if {@code key} is contained in the trie. */
+ public boolean contains(String key) {
+ return !get(key).isEmpty();
+ }
+
+ /** Return value stored at Node (in this case, a set of integers). */
+ public Set<Integer> get(String key) {
+ Node x = get(root, key, 0);
+ return x == null ? new ArraySet<>() : x.values;
+ }
+
+ private Node get(Node node, String key, int position) {
+ if (node == null) {
+ return null;
+ }
+ char c = key.charAt(position);
+ if (c < node.key) {
+ return get(node.left, key, position);
+ } else if (c > node.key) {
+ return get(node.right, key, position);
+ } else if (position < key.length() - 1) {
+ return get(node.mid, key, position + 1);
+ } else {
+ return node;
+ }
+ }
+
+ /** Node in ternary search trie. Children are denoted as left, middle and right nodes. */
+ private static class Node {
+ private char key;
+ private final Set<Integer> values = new ArraySet<>();
+
+ private Node left;
+ private Node mid;
+ private Node right;
+ }
+}
diff --git a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
index 8306d37a6..93263ceb2 100644
--- a/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
+++ b/java/com/android/dialer/searchfragment/list/NewSearchFragment.java
@@ -32,6 +32,7 @@ import android.support.annotation.VisibleForTesting;
import android.support.v13.app.FragmentCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
+import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -444,7 +445,9 @@ public final class NewSearchFragment extends Fragment
* the list of supported actions, see {@link SearchActionViewHolder.Action}.
*/
private List<Integer> getActions() {
- if (TextUtils.isEmpty(query) || query.length() == 1 || isRegularSearch()) {
+ boolean nonDialableQueryInRegularSearch =
+ isRegularSearch() && !PhoneNumberUtils.isGlobalPhoneNumber(query);
+ if (TextUtils.isEmpty(query) || query.length() == 1 || nonDialableQueryInRegularSearch) {
return Collections.emptyList();
}
diff --git a/java/com/android/dialer/telecom/TelecomUtil.java b/java/com/android/dialer/telecom/TelecomUtil.java
index 3bf9b4666..c79d9013d 100644
--- a/java/com/android/dialer/telecom/TelecomUtil.java
+++ b/java/com/android/dialer/telecom/TelecomUtil.java
@@ -33,9 +33,12 @@ import android.support.v4.content.ContextCompat;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.text.TextUtils;
import android.util.Pair;
import com.android.dialer.common.LogUtil;
+import com.google.common.base.Optional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -146,6 +149,24 @@ public abstract class TelecomUtil {
}
/**
+ * @return the {@link SubscriptionInfo} of the SIM if {@code phoneAccountHandle} corresponds to a
+ * valid SIM. Absent otherwise.
+ */
+ public static Optional<SubscriptionInfo> getSubscriptionInfo(
+ @NonNull Context context, @NonNull PhoneAccountHandle phoneAccountHandle) {
+ if (TextUtils.isEmpty(phoneAccountHandle.getId())) {
+ return Optional.absent();
+ }
+ SubscriptionManager subscriptionManager = context.getSystemService(SubscriptionManager.class);
+ for (SubscriptionInfo info : subscriptionManager.getActiveSubscriptionInfoList()) {
+ if (phoneAccountHandle.getId().startsWith(info.getIccId())) {
+ return Optional.of(info);
+ }
+ }
+ return Optional.absent();
+ }
+
+ /**
* Returns true if there is a dialer managed call in progress. Self managed calls starting from O
* are not included.
*/
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java b/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
index 4629ce277..d5db60846 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailMediaPlayerView.java
@@ -30,7 +30,7 @@ import android.support.v4.util.Pair;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
-import android.widget.Button;
+import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.dialer.common.Assert;
@@ -45,9 +45,10 @@ import com.android.dialer.voicemail.model.VoicemailEntry;
*/
public class NewVoicemailMediaPlayerView extends LinearLayout {
- private Button playButton;
- private Button speakerButton;
- private Button deleteButton;
+ private ImageButton playButton;
+ private ImageButton speakerButton;
+ private ImageButton phoneButton;
+ private ImageButton deleteButton;
private TextView totalDurationView;
private Uri voicemailUri;
private FragmentManager fragmentManager;
@@ -72,6 +73,7 @@ public class NewVoicemailMediaPlayerView extends LinearLayout {
private void initializeMediaPlayerButtonsAndViews() {
playButton = findViewById(R.id.playButton);
speakerButton = findViewById(R.id.speakerButton);
+ phoneButton = findViewById(R.id.phoneButton);
deleteButton = findViewById(R.id.deleteButton);
totalDurationView = findViewById(R.id.playback_seek_total_duration);
}
@@ -79,6 +81,7 @@ public class NewVoicemailMediaPlayerView extends LinearLayout {
private void setupListenersForMediaPlayerButtons() {
playButton.setOnClickListener(playButtonListener);
speakerButton.setOnClickListener(speakerButtonListener);
+ phoneButton.setOnClickListener(phoneButtonListener);
deleteButton.setOnClickListener(deleteButtonListener);
}
@@ -164,6 +167,17 @@ public class NewVoicemailMediaPlayerView extends LinearLayout {
}
};
+ private final View.OnClickListener phoneButtonListener =
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ LogUtil.i(
+ "NewVoicemailMediaPlayer.phoneButtonListener",
+ "speaker request for voicemailUri: %s",
+ voicemailUri.toString());
+ }
+ };
+
private final View.OnClickListener deleteButtonListener =
new View.OnClickListener() {
@Override
diff --git a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_media_player_layout.xml b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_media_player_layout.xml
index e8e560059..07ce86a1d 100644
--- a/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_media_player_layout.xml
+++ b/java/com/android/dialer/voicemail/listui/res/layout/new_voicemail_media_player_layout.xml
@@ -67,22 +67,36 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="10dp"
- android:orientation="horizontal">
- <!-- TODO(a bug): Remove these buttons as this is a place holder for the Media Player -->
- <Button
+ android:gravity="center"
+ android:orientation="horizontal"
+ android:weightSum="4">
+
+
+ <ImageButton
android:id="@+id/playButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Play"/>
- <Button
+ style="@style/voicemail_media_player_buttons"
+ android:layout_weight="1"
+ android:src="@drawable/quantum_ic_play_arrow_vd_theme_24"/>
+
+
+ <ImageButton
android:id="@+id/speakerButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Speaker"/>
- <Button
+ style="@style/voicemail_media_player_buttons"
+ android:layout_weight="1"
+ android:src="@drawable/quantum_ic_volume_up_vd_theme_24"/>
+
+
+ <ImageButton
+ android:id="@+id/phoneButton"
+ style="@style/voicemail_media_player_buttons"
+ android:layout_weight="1"
+ android:src="@drawable/quantum_ic_phone_vd_theme_24"/>
+
+ <ImageButton
android:id="@+id/deleteButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="Delete"/>
+ style="@style/voicemail_media_player_buttons"
+ android:layout_weight="1"
+ android:src="@drawable/quantum_ic_delete_vd_theme_24"/>
+
</LinearLayout>
</LinearLayout> \ No newline at end of file
diff --git a/java/com/android/dialer/voicemail/listui/res/values/dimens.xml b/java/com/android/dialer/voicemail/listui/res/values/dimens.xml
index 6c062ae28..e37bc65fe 100644
--- a/java/com/android/dialer/voicemail/listui/res/values/dimens.xml
+++ b/java/com/android/dialer/voicemail/listui/res/values/dimens.xml
@@ -29,6 +29,11 @@
<dimen name="voicemail_icon_size">16dp</dimen>
<dimen name="voicemail_playback_state_text_size">14sp</dimen>
+ <!-- TODO(uabdullah): Work with UX on this value to ensure proper spacing between
+ the seekbar and transcription -->
<dimen name="voicemail_media_player_padding_top">20dp</dimen>
<dimen name="voicemail_duration_size">14sp</dimen>
+ <!-- TODO(uabdullah): Work with UX on these values so that the touch target is not too small -->
+ <dimen name="voicemail_media_player_height">56dp</dimen>
+ <dimen name="voicemail_media_player_width">0dp</dimen>
</resources>
diff --git a/java/com/android/dialer/voicemail/listui/res/values/styles.xml b/java/com/android/dialer/voicemail/listui/res/values/styles.xml
new file mode 100644
index 000000000..aec46090a
--- /dev/null
+++ b/java/com/android/dialer/voicemail/listui/res/values/styles.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+
+<resources>
+
+ <style name="voicemail_media_player_buttons">
+ <item name="android:layout_width">@dimen/voicemail_media_player_width</item>
+ <item name="android:layout_height">@dimen/voicemail_media_player_height</item>
+ <item name="android:background">?android:attr/selectableItemBackgroundBorderless</item>
+ </style>
+</resources> \ No newline at end of file
diff --git a/java/com/android/dialer/voicemail/settings/VoicemailSettingsFragment.java b/java/com/android/dialer/voicemail/settings/VoicemailSettingsFragment.java
index 2b496c0ca..aaa1e150d 100644
--- a/java/com/android/dialer/voicemail/settings/VoicemailSettingsFragment.java
+++ b/java/com/android/dialer/voicemail/settings/VoicemailSettingsFragment.java
@@ -24,16 +24,22 @@ import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import android.provider.Settings;
import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.notification.NotificationChannelManager;
+import com.android.dialer.telecom.TelecomUtil;
import com.android.voicemail.VoicemailClient;
import com.android.voicemail.VoicemailClient.ActivationStateListener;
import com.android.voicemail.VoicemailComponent;
+import com.google.common.base.Optional;
/**
* Fragment for voicemail settings. Requires {@link VoicemailClient#PARAM_PHONE_ACCOUNT_HANDLE} set
@@ -45,6 +51,16 @@ public class VoicemailSettingsFragment extends PreferenceFragment
private static final String TAG = "VmSettingsActivity";
+ // Extras copied from com.android.phone.settings.VoicemailSettingsActivity,
+ // it does not recognize EXTRA_PHONE_ACCOUNT_HANDLE in O.
+ @VisibleForTesting
+ static final String SUB_ID_EXTRA =
+ "com.android.phone.settings.SubscriptionInfoHelper.SubscriptionId";
+ // Extra on intent containing the label of a subscription.
+ @VisibleForTesting
+ static final String SUB_LABEL_EXTRA =
+ "com.android.phone.settings.SubscriptionInfoHelper.SubscriptionLabel";
+
@Nullable private PhoneAccountHandle phoneAccountHandle;
private VoicemailClient voicemailClient;
@@ -167,6 +183,19 @@ public class VoicemailSettingsFragment extends PreferenceFragment
advancedSettingsIntent.putExtra(TelephonyManager.EXTRA_HIDE_PUBLIC_SETTINGS, true);
advancedSettingsIntent.putExtra(
TelephonyManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
+
+ // (a bug): EXTRA_PHONE_ACCOUNT_HANDLE not implemented in telephony in O.
+ Optional<SubscriptionInfo> subscriptionInfo =
+ TelecomUtil.getSubscriptionInfo(getContext(), phoneAccountHandle);
+ if (subscriptionInfo.isPresent()) {
+ advancedSettingsIntent.putExtra(SUB_ID_EXTRA, subscriptionInfo.get().getSubscriptionId());
+ PhoneAccount phoneAccount =
+ getContext().getSystemService(TelecomManager.class).getPhoneAccount(phoneAccountHandle);
+ if (phoneAccount != null) {
+ advancedSettingsIntent.putExtra(SUB_LABEL_EXTRA, phoneAccount.getLabel());
+ }
+ }
+
advancedSettings.setIntent(advancedSettingsIntent);
voicemailChangePinPreference.setOnPreferenceClickListener(
new OnPreferenceClickListener() {
diff --git a/java/com/android/dialer/widget/FloatingActionButtonController.java b/java/com/android/dialer/widget/FloatingActionButtonController.java
index a0c4e6ddd..dde4d44ce 100644
--- a/java/com/android/dialer/widget/FloatingActionButtonController.java
+++ b/java/com/android/dialer/widget/FloatingActionButtonController.java
@@ -18,7 +18,7 @@ package com.android.dialer.widget;
import android.app.Activity;
import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
+import android.support.annotation.DrawableRes;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.FloatingActionButton.OnVisibilityChangedListener;
import android.view.View;
@@ -39,6 +39,7 @@ public class FloatingActionButtonController {
private final int mFloatingActionButtonMarginRight;
private final FloatingActionButton mFab;
private final Interpolator mFabInterpolator;
+ private int mFabIconId = -1;
private int mScreenWidth;
public FloatingActionButtonController(Activity activity, FloatingActionButton fab) {
@@ -82,9 +83,12 @@ public class FloatingActionButtonController {
}
}
- public void changeIcon(Drawable icon, String description) {
- if (mFab.getDrawable() != icon || !mFab.getContentDescription().equals(description)) {
- mFab.setImageDrawable(icon);
+ public void changeIcon(@DrawableRes int iconId, String description) {
+ if (this.mFabIconId != iconId) {
+ mFab.setImageResource(iconId);
+ this.mFabIconId = iconId;
+ }
+ if (!mFab.getContentDescription().equals(description)) {
mFab.setContentDescription(description);
}
}
diff --git a/java/com/android/incallui/InCallActivity.java b/java/com/android/incallui/InCallActivity.java
index cdab6b4f5..ed10ed0bb 100644
--- a/java/com/android/incallui/InCallActivity.java
+++ b/java/com/android/incallui/InCallActivity.java
@@ -16,6 +16,8 @@
package com.android.incallui;
+import android.app.AlertDialog;
+import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.GradientDrawable;
@@ -34,6 +36,10 @@ import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+import android.widget.Toast;
+import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.ThreadUtil;
@@ -59,6 +65,8 @@ import com.android.incallui.incall.protocol.InCallButtonUiDelegateFactory;
import com.android.incallui.incall.protocol.InCallScreen;
import com.android.incallui.incall.protocol.InCallScreenDelegate;
import com.android.incallui.incall.protocol.InCallScreenDelegateFactory;
+import com.android.incallui.incalluilock.InCallUiLock;
+import com.android.incallui.telecomeventui.InternationalCallOnWifiDialogFragment;
import com.android.incallui.video.bindings.VideoBindings;
import com.android.incallui.video.protocol.VideoCallScreen;
import com.android.incallui.video.protocol.VideoCallScreenDelegate;
@@ -76,8 +84,10 @@ public class InCallActivity extends TransactionSafeFragmentActivity
public static final int PENDING_INTENT_REQUEST_CODE_FULL_SCREEN = 1;
public static final int PENDING_INTENT_REQUEST_CODE_BUBBLE = 2;
- private static final String TAG_IN_CALL_SCREEN = "tag_in_call_screen";
private static final String TAG_ANSWER_SCREEN = "tag_answer_screen";
+ private static final String TAG_DIALPAD_FRAGMENT = "tag_dialpad_fragment";
+ private static final String TAG_INTERNATIONAL_CALL_ON_WIFI = "tag_international_call_on_wifi";
+ private static final String TAG_IN_CALL_SCREEN = "tag_in_call_screen";
private static final String TAG_VIDEO_CALL_SCREEN = "tag_video_call_screen";
private static final String DID_SHOW_ANSWER_SCREEN_KEY = "did_show_answer_screen";
@@ -87,9 +97,11 @@ public class InCallActivity extends TransactionSafeFragmentActivity
private static final String CONFIG_ANSWER_AND_RELEASE_ENABLED = "answer_and_release_enabled";
private final InCallActivityCommon common;
+ private InCallOrientationEventListener inCallOrientationEventListener;
private boolean didShowAnswerScreen;
private boolean didShowInCallScreen;
private boolean didShowVideoCallScreen;
+ private boolean dismissKeyguard;
private int[] backgroundDrawableColors;
private GradientDrawable backgroundDrawable;
private boolean isVisible;
@@ -138,6 +150,7 @@ public class InCallActivity extends TransactionSafeFragmentActivity
}
common.onCreate(icicle);
+ inCallOrientationEventListener = new InCallOrientationEventListener(this);
getWindow()
.getDecorView()
@@ -340,7 +353,21 @@ public class InCallActivity extends TransactionSafeFragmentActivity
}
public boolean isDialpadVisible() {
- return common.isDialpadVisible();
+ DialpadFragment dialpadFragment = getDialpadFragment();
+ return dialpadFragment != null && dialpadFragment.isVisible();
+ }
+
+ /**
+ * Returns the {@link DialpadFragment} that's shown by this activity, or {@code null}
+ * TODO(a bug): Make this method private after InCallActivityCommon is deleted.
+ */
+ @Nullable
+ DialpadFragment getDialpadFragment() {
+ FragmentManager fragmentManager = getDialpadFragmentManager();
+ if (fragmentManager == null) {
+ return null;
+ }
+ return (DialpadFragment) fragmentManager.findFragmentByTag(TAG_DIALPAD_FRAGMENT);
}
public void onForegroundCallChanged(DialerCall newForegroundCall) {
@@ -419,37 +446,109 @@ public class InCallActivity extends TransactionSafeFragmentActivity
}
public void dismissKeyguard(boolean dismiss) {
- common.dismissKeyguard(dismiss);
+ if (dismissKeyguard == dismiss) {
+ return;
+ }
+
+ dismissKeyguard = dismiss;
+ if (dismiss) {
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+ } else {
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
+ }
}
public void showPostCharWaitDialog(String callId, String chars) {
common.showPostCharWaitDialog(callId, chars);
}
- public void maybeShowErrorDialogOnDisconnect(DisconnectMessage disconnectMessage) {
- common.maybeShowErrorDialogOnDisconnect(disconnectMessage);
+ public void showDialogOrToastForDisconnectedCall(DisconnectMessage disconnectMessage) {
+ LogUtil.i(
+ "InCallActivity.showDialogOrToastForDisconnectedCall",
+ "disconnect cause: %s",
+ disconnectMessage);
+
+ if (disconnectMessage.dialog == null || isFinishing()) {
+ return;
+ }
+
+ dismissPendingDialogs();
+
+ // Show a toast if the app is in background when a dialog can't be visible.
+ if (!isVisible()) {
+ Toast.makeText(getApplicationContext(), disconnectMessage.toastMessage, Toast.LENGTH_LONG)
+ .show();
+ return;
+ }
+
+ // Show the dialog.
+ common.setErrorDialog(disconnectMessage.dialog);
+ InCallUiLock lock = InCallPresenter.getInstance().acquireInCallUiLock("showErrorDialog");
+ disconnectMessage.dialog.setOnDismissListener(
+ dialogInterface -> {
+ lock.release();
+ onDialogDismissed();
+ });
+ disconnectMessage.dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+ disconnectMessage.dialog.show();
+ }
+
+ private void onDialogDismissed() {
+ common.setErrorDialog(null);
+ CallList.getInstance().onErrorDialogDismissed();
}
public void dismissPendingDialogs() {
- if (isVisible) {
- LogUtil.i("InCallActivity.dismissPendingDialogs", "");
- common.dismissPendingDialogs();
- AnswerScreen answerScreen = getAnswerScreen();
- if (answerScreen != null) {
- answerScreen.dismissPendingDialogs();
- }
- needDismissPendingDialogs = false;
- } else {
- // The activity is not visible and onSaveInstanceState may have been called so defer the
- // dismissing action.
+ LogUtil.i("InCallActivity.dismissPendingDialogs", "");
+
+ if (!isVisible) {
+ // Defer the dismissing action as the activity is not visible and onSaveInstanceState may have
+ // been called.
LogUtil.i(
"InCallActivity.dismissPendingDialogs", "defer actions since activity is not visible");
needDismissPendingDialogs = true;
+ return;
+ }
+
+ // Dismiss the error dialog
+ Dialog errorDialog = common.getErrorDialog();
+ if (errorDialog != null) {
+ errorDialog.dismiss();
+ common.setErrorDialog(null);
+ }
+
+ // Dismiss the phone account selection dialog
+ SelectPhoneAccountDialogFragment selectPhoneAccountDialogFragment =
+ common.getSelectPhoneAccountDialogFragment();
+ if (selectPhoneAccountDialogFragment != null) {
+ selectPhoneAccountDialogFragment.dismiss();
+ common.setSelectPhoneAccountDialogFragment(null);
+ }
+
+ // Dismiss the dialog for international call on WiFi
+ InternationalCallOnWifiDialogFragment internationalCallOnWifiFragment =
+ (InternationalCallOnWifiDialogFragment)
+ getSupportFragmentManager().findFragmentByTag(TAG_INTERNATIONAL_CALL_ON_WIFI);
+ if (internationalCallOnWifiFragment != null) {
+ internationalCallOnWifiFragment.dismiss();
+ }
+
+ // Dismiss the answer screen
+ AnswerScreen answerScreen = getAnswerScreen();
+ if (answerScreen != null) {
+ answerScreen.dismissPendingDialogs();
}
+
+ needDismissPendingDialogs = false;
}
- private void enableInCallOrientationEventListener(boolean enable) {
- common.enableInCallOrientationEventListener(enable);
+ // TODO(a bug): Make this method private after InCallActivityCommon is deleted.
+ void enableInCallOrientationEventListener(boolean enable) {
+ if (enable) {
+ inCallOrientationEventListener.enable(true /* notifyDeviceOrientationChange */);
+ } else {
+ inCallOrientationEventListener.disable();
+ }
}
public void setExcludeFromRecents(boolean exclude) {
@@ -515,17 +614,67 @@ public class InCallActivity extends TransactionSafeFragmentActivity
Trace.endSection();
}
- public void onWiFiToLteHandover(DialerCall call) {
- common.showWifiToLteHandoverToast(call);
- }
+ public void showToastForWiFiToLteHandover(DialerCall call) {
+ if (call.hasShownWiFiToLteHandoverToast()) {
+ return;
+ }
- public void onHandoverToWifiFailed(DialerCall call) {
- common.showWifiFailedDialog(call);
+ Toast.makeText(this, R.string.video_call_wifi_to_lte_handover_toast, Toast.LENGTH_LONG).show();
+ call.setHasShownWiFiToLteHandoverToast();
}
- public void onInternationalCallOnWifi(@NonNull DialerCall call) {
- LogUtil.enterBlock("InCallActivity.onInternationalCallOnWifi");
- common.showInternationalCallOnWifiDialog(call);
+ public void showDialogOrToastForWifiHandoverFailure(DialerCall call) {
+ if (call.showWifiHandoverAlertAsToast()) {
+ Toast.makeText(this, R.string.video_call_lte_to_wifi_failed_message, Toast.LENGTH_SHORT)
+ .show();
+ return;
+ }
+
+ dismissPendingDialogs();
+
+ AlertDialog.Builder builder =
+ new AlertDialog.Builder(this).setTitle(R.string.video_call_lte_to_wifi_failed_title);
+
+ // This allows us to use the theme of the dialog instead of the activity
+ View dialogCheckBoxView =
+ View.inflate(builder.getContext(), R.layout.video_call_lte_to_wifi_failed, null /* root */);
+ CheckBox wifiHandoverFailureCheckbox =
+ (CheckBox) dialogCheckBoxView.findViewById(R.id.video_call_lte_to_wifi_failed_checkbox);
+ wifiHandoverFailureCheckbox.setChecked(false);
+
+ InCallUiLock lock = InCallPresenter.getInstance().acquireInCallUiLock("WifiFailedDialog");
+ Dialog errorDialog =
+ builder
+ .setView(dialogCheckBoxView)
+ .setMessage(R.string.video_call_lte_to_wifi_failed_message)
+ .setOnCancelListener(dialogInterface -> onDialogDismissed())
+ .setPositiveButton(
+ android.R.string.ok,
+ (dialogInterface, id) -> {
+ call.setDoNotShowDialogForHandoffToWifiFailure(
+ wifiHandoverFailureCheckbox.isChecked());
+ dialogInterface.cancel();
+ onDialogDismissed();
+ })
+ .setOnDismissListener(dialogInterface -> lock.release())
+ .create();
+
+ common.setErrorDialog(errorDialog);
+ errorDialog.show();
+ }
+
+ public void showDialogForInternationalCallOnWifi(@NonNull DialerCall call) {
+ if (!InternationalCallOnWifiDialogFragment.shouldShow(this)) {
+ LogUtil.i(
+ "InCallActivity.showDialogForInternationalCallOnWifi",
+ "InternationalCallOnWifiDialogFragment.shouldShow returned false");
+ return;
+ }
+
+ InternationalCallOnWifiDialogFragment fragment =
+ InternationalCallOnWifiDialogFragment.newInstance(
+ call.getId(), common.getCallbackForInternationalCallOnWifiDialog());
+ fragment.show(getSupportFragmentManager(), TAG_INTERNATIONAL_CALL_ON_WIFI);
}
@Override
diff --git a/java/com/android/incallui/InCallActivityCommon.java b/java/com/android/incallui/InCallActivityCommon.java
index 5a5d770d0..8f82295ed 100644
--- a/java/com/android/incallui/InCallActivityCommon.java
+++ b/java/com/android/incallui/InCallActivityCommon.java
@@ -19,12 +19,8 @@ package com.android.incallui;
import android.app.ActivityManager;
import android.app.ActivityManager.AppTask;
import android.app.ActivityManager.TaskDescription;
-import android.app.AlertDialog;
import android.app.Dialog;
import android.app.KeyguardManager;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -46,8 +42,6 @@ import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
-import android.widget.CheckBox;
-import android.widget.Toast;
import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment;
import com.android.contacts.common.widget.SelectPhoneAccountDialogFragment.SelectPhoneAccountListener;
import com.android.dialer.animation.AnimUtils;
@@ -63,8 +57,6 @@ import com.android.incallui.call.CallList;
import com.android.incallui.call.DialerCall;
import com.android.incallui.call.DialerCall.State;
import com.android.incallui.call.TelecomAdapter;
-import com.android.incallui.disconnectdialog.DisconnectMessage;
-import com.android.incallui.incalluilock.InCallUiLock;
import com.android.incallui.telecomeventui.InternationalCallOnWifiDialogFragment;
import com.android.incallui.telecomeventui.InternationalCallOnWifiDialogFragment.Callback;
import com.google.common.base.Optional;
@@ -102,13 +94,11 @@ public class InCallActivityCommon {
private static Optional<Integer> audioRouteForTesting = Optional.absent();
private final InCallActivity inCallActivity;
- private boolean dismissKeyguard;
private boolean showPostCharWaitDialogOnResume;
private String showPostCharWaitDialogCallId;
private String showPostCharWaitDialogChars;
- private Dialog dialog;
+ private Dialog errorDialog;
private SelectPhoneAccountDialogFragment selectPhoneAccountDialogFragment;
- private InCallOrientationEventListener inCallOrientationEventListener;
private Animation dialpadSlideInAnimation;
private Animation dialpadSlideOutAnimation;
private boolean animateDialpadOnShow;
@@ -243,14 +233,12 @@ public class InCallActivityCommon {
"InCallActivityCommon.onCreate", "international fragment exists attaching callback");
existingInternationalFragment.setCallback(internationalCallOnWifiCallback);
}
-
- inCallOrientationEventListener = new InCallOrientationEventListener(inCallActivity);
}
public void onSaveInstanceState(Bundle out) {
// TODO: The dialpad fragment should handle this as part of its own state
- out.putBoolean(INTENT_EXTRA_SHOW_DIALPAD, isDialpadVisible());
- DialpadFragment dialpadFragment = getDialpadFragment();
+ out.putBoolean(INTENT_EXTRA_SHOW_DIALPAD, inCallActivity.isDialpadVisible());
+ DialpadFragment dialpadFragment = inCallActivity.getDialpadFragment();
if (dialpadFragment != null) {
out.putString(DIALPAD_TEXT_KEY, dialpadFragment.getDtmfText());
}
@@ -260,14 +248,11 @@ public class InCallActivityCommon {
Trace.beginSection("InCallActivityCommon.onStart");
// setting activity should be last thing in setup process
InCallPresenter.getInstance().setActivity(inCallActivity);
- enableInCallOrientationEventListener(
+ inCallActivity.enableInCallOrientationEventListener(
inCallActivity.getRequestedOrientation()
== InCallOrientationEventListener.ACTIVITY_PREFERENCE_ALLOW_ROTATION);
InCallPresenter.getInstance().onActivityStarted();
- if (!isRecreating) {
- InCallPresenter.getInstance().onUiShowing(true);
- }
Trace.endSection();
}
@@ -279,6 +264,7 @@ public class InCallActivityCommon {
"InCallPresenter is ready for tear down, not sending updates");
} else {
updateTaskDescription();
+ InCallPresenter.getInstance().onUiShowing(true);
}
// If there is a pending request to show or hide the dialpad, handle that now.
@@ -291,20 +277,20 @@ public class InCallActivityCommon {
inCallActivity.showDialpadFragment(true /* show */, animateDialpadOnShow /* animate */);
animateDialpadOnShow = false;
- DialpadFragment dialpadFragment = getDialpadFragment();
+ DialpadFragment dialpadFragment = inCallActivity.getDialpadFragment();
if (dialpadFragment != null) {
dialpadFragment.setDtmfText(dtmfTextToPreopulate);
dtmfTextToPreopulate = null;
}
} else {
LogUtil.i("InCallActivityCommon.onResume", "force hide dialpad");
- if (getDialpadFragment() != null) {
+ if (inCallActivity.getDialpadFragment() != null) {
inCallActivity.showDialpadFragment(false /* show */, false /* animate */);
}
}
showDialpadRequest = DIALPAD_REQUEST_NONE;
}
- updateNavigationBar(isDialpadVisible());
+ updateNavigationBar(inCallActivity.isDialpadVisible());
if (showPostCharWaitDialogOnResume) {
showPostCharWaitDialog(showPostCharWaitDialogCallId, showPostCharWaitDialogChars);
@@ -319,10 +305,15 @@ public class InCallActivityCommon {
// onPause is guaranteed to be called when the InCallActivity goes
// in the background.
public void onPause() {
- DialpadFragment dialpadFragment = getDialpadFragment();
+ DialpadFragment dialpadFragment = inCallActivity.getDialpadFragment();
if (dialpadFragment != null) {
dialpadFragment.onDialerKeyUp(null);
}
+
+ InCallPresenter.getInstance().onUiShowing(false);
+ if (inCallActivity.isFinishing()) {
+ InCallPresenter.getInstance().unsetActivity(inCallActivity);
+ }
}
public void onStop() {
@@ -338,18 +329,14 @@ public class InCallActivityCommon {
}
}
- enableInCallOrientationEventListener(false);
+ inCallActivity.enableInCallOrientationEventListener(false);
InCallPresenter.getInstance().updateIsChangingConfigurations();
InCallPresenter.getInstance().onActivityStopped();
if (!isRecreating) {
- InCallPresenter.getInstance().onUiShowing(false);
- if (dialog != null) {
- dialog.dismiss();
+ if (errorDialog != null) {
+ errorDialog.dismiss();
}
}
- if (inCallActivity.isFinishing()) {
- InCallPresenter.getInstance().unsetActivity(inCallActivity);
- }
}
public void onDestroy() {
@@ -394,7 +381,7 @@ public class InCallActivityCommon {
return true;
}
- DialpadFragment dialpadFragment = getDialpadFragment();
+ DialpadFragment dialpadFragment = inCallActivity.getDialpadFragment();
if (dialpadFragment != null && dialpadFragment.isVisible()) {
inCallActivity.showDialpadFragment(false /* show */, true /* animate */);
return true;
@@ -412,7 +399,7 @@ public class InCallActivityCommon {
}
public boolean onKeyUp(int keyCode, KeyEvent event) {
- DialpadFragment dialpadFragment = getDialpadFragment();
+ DialpadFragment dialpadFragment = inCallActivity.getDialpadFragment();
// push input to the dialer.
if (dialpadFragment != null
&& (dialpadFragment.isVisible())
@@ -517,7 +504,7 @@ public class InCallActivityCommon {
// As soon as the user starts typing valid dialable keys on the
// keyboard (presumably to type DTMF tones) we start passing the
// key events to the DTMFDialer's onDialerKeyDown.
- DialpadFragment dialpadFragment = getDialpadFragment();
+ DialpadFragment dialpadFragment = inCallActivity.getDialpadFragment();
if (dialpadFragment != null && dialpadFragment.isVisible()) {
return dialpadFragment.onDialerKeyDown(event);
}
@@ -525,18 +512,6 @@ public class InCallActivityCommon {
return false;
}
- public void dismissKeyguard(boolean dismiss) {
- if (dismissKeyguard == dismiss) {
- return;
- }
- dismissKeyguard = dismiss;
- if (dismiss) {
- inCallActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
- } else {
- inCallActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
- }
- }
-
public void showPostCharWaitDialog(String callId, String chars) {
if (inCallActivity.isVisible()) {
PostCharDialogFragment fragment = new PostCharDialogFragment(callId, chars);
@@ -552,19 +527,6 @@ public class InCallActivityCommon {
}
}
- public void maybeShowErrorDialogOnDisconnect(DisconnectMessage disconnectMessage) {
- LogUtil.i(
- "InCallActivityCommon.maybeShowErrorDialogOnDisconnect",
- "disconnect cause: %s",
- disconnectMessage);
-
- if (!inCallActivity.isFinishing()) {
- if (disconnectMessage.dialog != null) {
- showErrorDialog(disconnectMessage.dialog, disconnectMessage.toastMessage);
- }
- }
- }
-
/**
* When relaunching from the dialer app, {@code showDialpad} indicates whether the dialpad should
* be shown on launch.
@@ -586,67 +548,6 @@ public class InCallActivityCommon {
}
}
- void dismissPendingDialogs() {
- if (dialog != null) {
- dialog.dismiss();
- dialog = null;
- }
- if (selectPhoneAccountDialogFragment != null) {
- selectPhoneAccountDialogFragment.dismiss();
- selectPhoneAccountDialogFragment = null;
- }
-
- InternationalCallOnWifiDialogFragment internationalCallOnWifiFragment =
- (InternationalCallOnWifiDialogFragment)
- inCallActivity
- .getSupportFragmentManager()
- .findFragmentByTag(TAG_INTERNATIONAL_CALL_ON_WIFI);
- if (internationalCallOnWifiFragment != null) {
- LogUtil.i(
- "InCallActivityCommon.dismissPendingDialogs",
- "dismissing InternationalCallOnWifiDialogFragment");
- internationalCallOnWifiFragment.dismiss();
- }
- }
-
- private void showErrorDialog(Dialog dialog, CharSequence message) {
- LogUtil.i("InCallActivityCommon.showErrorDialog", "message: %s", message);
- inCallActivity.dismissPendingDialogs();
-
- // Show toast if apps is in background when dialog won't be visible.
- if (!inCallActivity.isVisible()) {
- Toast.makeText(inCallActivity.getApplicationContext(), message, Toast.LENGTH_LONG).show();
- return;
- }
-
- this.dialog = dialog;
- InCallUiLock lock = InCallPresenter.getInstance().acquireInCallUiLock("showErrorDialog");
- dialog.setOnDismissListener(
- new OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- LogUtil.i("InCallActivityCommon.showErrorDialog", "dialog dismissed");
- lock.release();
- onDialogDismissed();
- }
- });
- dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
- dialog.show();
- }
-
- private void onDialogDismissed() {
- dialog = null;
- CallList.getInstance().onErrorDialogDismissed();
- }
-
- public void enableInCallOrientationEventListener(boolean enable) {
- if (enable) {
- inCallOrientationEventListener.enable(true);
- } else {
- inCallOrientationEventListener.disable();
- }
- }
-
public void setExcludeFromRecents(boolean exclude) {
List<AppTask> tasks = inCallActivity.getSystemService(ActivityManager.class).getAppTasks();
int taskId = inCallActivity.getTaskId();
@@ -665,83 +566,6 @@ public class InCallActivityCommon {
}
}
- void showInternationalCallOnWifiDialog(@NonNull DialerCall call) {
- LogUtil.enterBlock("InCallActivityCommon.showInternationalCallOnWifiDialog");
- if (!InternationalCallOnWifiDialogFragment.shouldShow(inCallActivity)) {
- LogUtil.i(
- "InCallActivityCommon.showInternationalCallOnWifiDialog",
- "InternationalCallOnWifiDialogFragment.shouldShow returned false");
- return;
- }
-
- InternationalCallOnWifiDialogFragment fragment =
- InternationalCallOnWifiDialogFragment.newInstance(
- call.getId(), internationalCallOnWifiCallback);
- fragment.show(inCallActivity.getSupportFragmentManager(), TAG_INTERNATIONAL_CALL_ON_WIFI);
- }
-
- public void showWifiToLteHandoverToast(DialerCall call) {
- if (call.hasShownWiFiToLteHandoverToast()) {
- return;
- }
- Toast.makeText(
- inCallActivity, R.string.video_call_wifi_to_lte_handover_toast, Toast.LENGTH_LONG)
- .show();
- call.setHasShownWiFiToLteHandoverToast();
- }
-
- public void showWifiFailedDialog(final DialerCall call) {
- if (call.showWifiHandoverAlertAsToast()) {
- LogUtil.i("InCallActivityCommon.showWifiFailedDialog", "as toast");
- Toast.makeText(
- inCallActivity, R.string.video_call_lte_to_wifi_failed_message, Toast.LENGTH_SHORT)
- .show();
- return;
- }
-
- dismissPendingDialogs();
-
- AlertDialog.Builder builder =
- new AlertDialog.Builder(inCallActivity)
- .setTitle(R.string.video_call_lte_to_wifi_failed_title);
-
- // This allows us to use the theme of the dialog instead of the activity
- View dialogCheckBoxView =
- View.inflate(builder.getContext(), R.layout.video_call_lte_to_wifi_failed, null);
- final CheckBox wifiHandoverFailureCheckbox =
- (CheckBox) dialogCheckBoxView.findViewById(R.id.video_call_lte_to_wifi_failed_checkbox);
- wifiHandoverFailureCheckbox.setChecked(false);
-
- InCallUiLock lock = InCallPresenter.getInstance().acquireInCallUiLock("WifiFailedDialog");
- dialog =
- builder
- .setView(dialogCheckBoxView)
- .setMessage(R.string.video_call_lte_to_wifi_failed_message)
- .setOnCancelListener(
- new OnCancelListener() {
- @Override
- public void onCancel(DialogInterface dialog) {
- onDialogDismissed();
- }
- })
- .setPositiveButton(
- android.R.string.ok,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- call.setDoNotShowDialogForHandoffToWifiFailure(
- wifiHandoverFailureCheckbox.isChecked());
- dialog.cancel();
- onDialogDismissed();
- }
- })
- .setOnDismissListener((dialog) -> lock.release())
- .create();
-
- LogUtil.i("InCallActivityCommon.showWifiFailedDialog", "as dialog");
- dialog.show();
- }
-
void updateNavigationBar(boolean isDialpadVisible) {
if (!ActivityCompat.isInMultiWindowMode(inCallActivity)) {
View navigationBarBackground =
@@ -754,7 +578,7 @@ public class InCallActivityCommon {
public boolean showDialpadFragment(boolean show, boolean animate) {
// If the dialpad is already visible, don't animate in. If it's gone, don't animate out.
- boolean isDialpadVisible = isDialpadVisible();
+ boolean isDialpadVisible = inCallActivity.isDialpadVisible();
LogUtil.i(
"InCallActivityCommon.showDialpadFragment",
"show: %b, animate: %b, " + "isDialpadVisible: %b",
@@ -783,9 +607,10 @@ public class InCallActivityCommon {
} else {
if (show) {
performShowDialpadFragment(dialpadFragmentManager);
- getDialpadFragment().animateShowDialpad();
+ inCallActivity.getDialpadFragment().animateShowDialpad();
}
- getDialpadFragment()
+ inCallActivity
+ .getDialpadFragment()
.getView()
.startAnimation(show ? dialpadSlideInAnimation : dialpadSlideOutAnimation);
}
@@ -800,7 +625,7 @@ public class InCallActivityCommon {
private void performShowDialpadFragment(@NonNull FragmentManager dialpadFragmentManager) {
FragmentTransaction transaction = dialpadFragmentManager.beginTransaction();
- DialpadFragment dialpadFragment = getDialpadFragment();
+ DialpadFragment dialpadFragment = inCallActivity.getDialpadFragment();
if (dialpadFragment == null) {
transaction.add(
inCallActivity.getDialpadContainerId(), new DialpadFragment(), TAG_DIALPAD_FRAGMENT);
@@ -833,21 +658,6 @@ public class InCallActivityCommon {
updateNavigationBar(false /* isDialpadVisible */);
}
- public boolean isDialpadVisible() {
- DialpadFragment dialpadFragment = getDialpadFragment();
- return dialpadFragment != null && dialpadFragment.isVisible();
- }
-
- /** Returns the {@link DialpadFragment} that's shown by this activity, or {@code null} */
- @Nullable
- private DialpadFragment getDialpadFragment() {
- FragmentManager fragmentManager = inCallActivity.getDialpadFragmentManager();
- if (fragmentManager == null) {
- return null;
- }
- return (DialpadFragment) fragmentManager.findFragmentByTag(TAG_DIALPAD_FRAGMENT);
- }
-
public void updateTaskDescription() {
Resources resources = inCallActivity.getResources();
int color;
@@ -864,10 +674,6 @@ public class InCallActivityCommon {
inCallActivity.setTaskDescription(td);
}
- public boolean hasPendingDialogs() {
- return dialog != null;
- }
-
private void internalResolveIntent(Intent intent) {
if (!intent.getAction().equals(Intent.ACTION_MAIN)) {
return;
@@ -902,7 +708,7 @@ public class InCallActivityCommon {
outgoingCall.disconnect();
}
- dismissKeyguard(true);
+ inCallActivity.dismissKeyguard(true);
}
boolean didShowAccountSelectionDialog = maybeShowAccountSelectionDialog();
@@ -937,4 +743,37 @@ public class InCallActivityCommon {
inCallActivity.getFragmentManager(), TAG_SELECT_ACCOUNT_FRAGMENT);
return true;
}
+
+ /** @deprecated Only for temporary use during the deprecation of {@link InCallActivityCommon} */
+ @Deprecated
+ @Nullable
+ Dialog getErrorDialog() {
+ return errorDialog;
+ }
+
+ /** @deprecated Only for temporary use during the deprecation of {@link InCallActivityCommon} */
+ @Deprecated
+ void setErrorDialog(@Nullable Dialog errorDialog) {
+ this.errorDialog = errorDialog;
+ }
+
+ /** @deprecated Only for temporary use during the deprecation of {@link InCallActivityCommon} */
+ @Deprecated
+ @Nullable
+ SelectPhoneAccountDialogFragment getSelectPhoneAccountDialogFragment() {
+ return selectPhoneAccountDialogFragment;
+ }
+
+ /** @deprecated Only for temporary use during the deprecation of {@link InCallActivityCommon} */
+ @Deprecated
+ void setSelectPhoneAccountDialogFragment(
+ @Nullable SelectPhoneAccountDialogFragment selectPhoneAccountDialogFragment) {
+ this.selectPhoneAccountDialogFragment = selectPhoneAccountDialogFragment;
+ }
+
+ /** @deprecated Only for temporary use during the deprecation of {@link InCallActivityCommon} */
+ @Deprecated
+ InternationalCallOnWifiDialogFragment.Callback getCallbackForInternationalCallOnWifiDialog() {
+ return internationalCallOnWifiCallback;
+ }
}
diff --git a/java/com/android/incallui/InCallOrientationEventListener.java b/java/com/android/incallui/InCallOrientationEventListener.java
index e6b0bc027..8aae6fb37 100644
--- a/java/com/android/incallui/InCallOrientationEventListener.java
+++ b/java/com/android/incallui/InCallOrientationEventListener.java
@@ -126,12 +126,13 @@ public class InCallOrientationEventListener extends OrientationEventListener {
}
/**
- * Enables the OrientationEventListener and notifies listeners of current orientation if notify
- * flag is true
+ * Enables the OrientationEventListener and optionally notifies listeners of the current
+ * orientation.
*
- * @param notify true or false. Notify device orientation changed if true.
+ * @param notifyDeviceOrientationChange Whether to notify listeners that the device orientation is
+ * changed.
*/
- public void enable(boolean notify) {
+ public void enable(boolean notifyDeviceOrientationChange) {
if (mEnabled) {
Log.v(this, "enable: Orientation listener is already enabled. Ignoring...");
return;
@@ -139,15 +140,15 @@ public class InCallOrientationEventListener extends OrientationEventListener {
super.enable();
mEnabled = true;
- if (notify) {
+ if (notifyDeviceOrientationChange) {
InCallPresenter.getInstance().onDeviceOrientationChange(sCurrentOrientation);
}
}
- /** Enables the OrientationEventListener with notify flag defaulting to false. */
+ /** Enables the OrientationEventListener. */
@Override
public void enable() {
- enable(false);
+ enable(false /* notifyDeviceOrientationChange */);
}
/** Disables the OrientationEventListener. */
diff --git a/java/com/android/incallui/InCallPresenter.java b/java/com/android/incallui/InCallPresenter.java
index 6c1c13027..3ba2ccff6 100644
--- a/java/com/android/incallui/InCallPresenter.java
+++ b/java/com/android/incallui/InCallPresenter.java
@@ -88,8 +88,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class InCallPresenter implements CallList.Listener, AudioModeProvider.AudioModeListener {
private static final String PIXEL2017_SYSTEM_FEATURE =
"com.google.android.feature.PIXEL_2017_EXPERIENCE";
- private static final String EXTRA_FIRST_TIME_SHOWN =
- "com.android.incallui.intent.extra.FIRST_TIME_SHOWN";
private static final long BLOCK_QUERY_TIMEOUT_MS = 1000;
@@ -215,14 +213,7 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud
}
}
};
- /**
- * Is true when the activity has been previously started. Some code needs to know not just if the
- * activity is currently up, but if it had been previously shown in foreground for this in-call
- * session (e.g., StatusBarNotifier). This gets reset when the session ends in the tear-down
- * method.
- */
- private boolean mIsActivityPreviouslyStarted = false;
-
+
/** Whether or not InCallService is bound to Telecom. */
private boolean mServiceBound = false;
@@ -476,7 +467,7 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud
// By the time the UI finally comes up, the call may already be disconnected.
// If that's the case, we may need to show an error dialog.
if (mCallList != null && mCallList.getDisconnectedCall() != null) {
- maybeShowErrorDialogOnDisconnect(mCallList.getDisconnectedCall());
+ showDialogOrToastForDisconnectedCall(mCallList.getDisconnectedCall());
}
// When the UI comes up, we need to first check the in-call state.
@@ -690,14 +681,14 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud
@Override
public void onWiFiToLteHandover(DialerCall call) {
if (mInCallActivity != null) {
- mInCallActivity.onWiFiToLteHandover(call);
+ mInCallActivity.showToastForWiFiToLteHandover(call);
}
}
@Override
public void onHandoverToWifiFailed(DialerCall call) {
if (mInCallActivity != null) {
- mInCallActivity.onHandoverToWifiFailed(call);
+ mInCallActivity.showDialogOrToastForWifiHandoverFailure(call);
}
}
@@ -705,7 +696,7 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud
public void onInternationalCallOnWifi(@NonNull DialerCall call) {
LogUtil.enterBlock("InCallPresenter.onInternationalCallOnWifi");
if (mInCallActivity != null) {
- mInCallActivity.onInternationalCallOnWifi(call);
+ mInCallActivity.showDialogForInternationalCallOnWifi(call);
}
}
@@ -841,7 +832,7 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud
*/
@Override
public void onDisconnect(DialerCall call) {
- maybeShowErrorDialogOnDisconnect(call);
+ showDialogOrToastForDisconnectedCall(call);
// We need to do the run the same code as onCallListChange.
onCallListChange(mCallList);
@@ -1052,22 +1043,7 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud
mProximitySensor.onInCallShowing(showing);
}
- Intent broadcastIntent = Bindings.get(mContext).getUiReadyBroadcastIntent(mContext);
- if (broadcastIntent != null) {
- broadcastIntent.putExtra(EXTRA_FIRST_TIME_SHOWN, !mIsActivityPreviouslyStarted);
-
- if (showing) {
- LogUtil.d("InCallPresenter.onUiShowing", "Sending sticky broadcast: ", broadcastIntent);
- mContext.sendStickyBroadcast(broadcastIntent);
- } else {
- LogUtil.d("InCallPresenter.onUiShowing", "Removing sticky broadcast: ", broadcastIntent);
- mContext.removeStickyBroadcast(broadcastIntent);
- }
- }
-
- if (showing) {
- mIsActivityPreviouslyStarted = true;
- } else {
+ if (!showing) {
updateIsChangingConfigurations();
}
@@ -1265,19 +1241,19 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud
}
}
- /**
- * For some disconnected causes, we show a dialog. This calls into the activity to show the dialog
- * if appropriate for the call.
- */
- private void maybeShowErrorDialogOnDisconnect(DialerCall call) {
+ /** Instruct the in-call activity to show an error dialog or toast for a disconnected call. */
+ private void showDialogOrToastForDisconnectedCall(DialerCall call) {
+ if (!isActivityStarted() || call.getState() != DialerCall.State.DISCONNECTED) {
+ return;
+ }
+
// For newly disconnected calls, we may want to show a dialog on specific error conditions
- if (isActivityStarted() && call.getState() == DialerCall.State.DISCONNECTED) {
- if (call.getAccountHandle() == null && !call.isConferenceCall()) {
- setDisconnectCauseForMissingAccounts(call);
- }
- mInCallActivity.maybeShowErrorDialogOnDisconnect(
- new DisconnectMessage(mInCallActivity, call));
+ if (call.getAccountHandle() == null && !call.isConferenceCall()) {
+ setDisconnectCauseForMissingAccounts(call);
}
+
+ mInCallActivity.showDialogOrToastForDisconnectedCall(
+ new DisconnectMessage(mInCallActivity, call));
}
/**
@@ -1449,7 +1425,6 @@ public class InCallPresenter implements CallList.Listener, AudioModeProvider.Aud
cleanupSurfaces();
- mIsActivityPreviouslyStarted = false;
mIsChangingConfigurations = false;
// blow away stale contact info so that we get fresh data on
diff --git a/java/com/android/incallui/bindings/InCallUiBindings.java b/java/com/android/incallui/bindings/InCallUiBindings.java
index 5c6aef4be..c15b68de9 100644
--- a/java/com/android/incallui/bindings/InCallUiBindings.java
+++ b/java/com/android/incallui/bindings/InCallUiBindings.java
@@ -26,10 +26,6 @@ public interface InCallUiBindings {
@Nullable
PhoneNumberService newPhoneNumberService(Context context);
- /** @return An {@link Intent} to be broadcast when the InCallUI is visible. */
- @Nullable
- Intent getUiReadyBroadcastIntent(Context context);
-
/**
* @return An {@link Intent} to be broadcast when the call state button in the InCallUI is touched
* while in a call.
diff --git a/java/com/android/incallui/bindings/InCallUiBindingsStub.java b/java/com/android/incallui/bindings/InCallUiBindingsStub.java
index 3a005b0fb..3a9e1dc52 100644
--- a/java/com/android/incallui/bindings/InCallUiBindingsStub.java
+++ b/java/com/android/incallui/bindings/InCallUiBindingsStub.java
@@ -31,12 +31,6 @@ public class InCallUiBindingsStub implements InCallUiBindings {
@Override
@Nullable
- public Intent getUiReadyBroadcastIntent(Context context) {
- return null;
- }
-
- @Override
- @Nullable
public Intent getCallStateButtonBroadcastIntent(Context context) {
return null;
}
diff --git a/java/com/android/incallui/incall/impl/ButtonController.java b/java/com/android/incallui/incall/impl/ButtonController.java
index cefbd723b..5e37a492b 100644
--- a/java/com/android/incallui/incall/impl/ButtonController.java
+++ b/java/com/android/incallui/incall/impl/ButtonController.java
@@ -16,6 +16,7 @@
package com.android.incallui.incall.impl;
+import android.graphics.drawable.AnimationDrawable;
import android.support.annotation.CallSuper;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
@@ -569,11 +570,14 @@ interface ButtonController {
InCallButtonIds.BUTTON_SWAP_SIM,
R.string.incall_content_description_swap_sim,
R.string.incall_label_swap_sim,
- R.drawable.quantum_ic_swap_calls_white_36);
+ R.drawable.ic_sim_change_white);
}
@Override
public void onClick(View view) {
+ AnimationDrawable drawable = (AnimationDrawable) button.getIconDrawable();
+ drawable.stop(); // animation is one shot, stop it so it can be started again.
+ drawable.start();
delegate.swapSimClicked();
}
}
diff --git a/java/com/android/incallui/incall/impl/CheckableLabeledButton.java b/java/com/android/incallui/incall/impl/CheckableLabeledButton.java
index 325c3a92a..ca018acc2 100644
--- a/java/com/android/incallui/incall/impl/CheckableLabeledButton.java
+++ b/java/com/android/incallui/incall/impl/CheckableLabeledButton.java
@@ -47,6 +47,7 @@ public class CheckableLabeledButton extends LinearLayout implements Checkable {
private boolean isChecked;
private OnCheckedChangeListener onCheckedChangeListener;
private ImageView iconView;
+ @DrawableRes private int iconResource = 0;
private TextView labelView;
private Drawable background;
private Drawable backgroundMore;
@@ -135,8 +136,15 @@ public class CheckableLabeledButton extends LinearLayout implements Checkable {
new int[] {color, Color.WHITE}));
}
+ public Drawable getIconDrawable() {
+ return iconView.getDrawable();
+ }
+
public void setIconDrawable(@DrawableRes int drawableRes) {
- iconView.setImageResource(drawableRes);
+ if (iconResource != drawableRes) {
+ iconView.setImageResource(drawableRes);
+ iconResource = drawableRes;
+ }
}
public void setLabelText(@StringRes int stringRes) {
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_00.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_00.png
new file mode 100644
index 000000000..4c8b33f95
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_00.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_01.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_01.png
new file mode 100644
index 000000000..910177920
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_01.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_02.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_02.png
new file mode 100644
index 000000000..92a27eed2
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_02.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_03.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_03.png
new file mode 100644
index 000000000..484058f22
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_03.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_04.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_04.png
new file mode 100644
index 000000000..348ae927a
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_04.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_05.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_05.png
new file mode 100644
index 000000000..011915a93
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_05.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_06.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_06.png
new file mode 100644
index 000000000..c1cc0d6d7
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_06.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_07.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_07.png
new file mode 100644
index 000000000..75233db73
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_07.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_08.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_08.png
new file mode 100644
index 000000000..2918e1a4b
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_08.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_09.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_09.png
new file mode 100644
index 000000000..7e927674c
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_09.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_10.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_10.png
new file mode 100644
index 000000000..008931431
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_10.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_11.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_11.png
new file mode 100644
index 000000000..f66a6b669
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_11.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_12.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_12.png
new file mode 100644
index 000000000..9303d9596
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_12.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_13.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_13.png
new file mode 100644
index 000000000..d2bef6e77
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_13.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_14.png b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_14.png
new file mode 100644
index 000000000..a5434ecdc
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable-xxxhdpi/ic_sim_change_white_14.png
Binary files differ
diff --git a/java/com/android/incallui/incall/impl/res/drawable/ic_sim_change_white.xml b/java/com/android/incallui/incall/impl/res/drawable/ic_sim_change_white.xml
new file mode 100644
index 000000000..00b1b7ace
--- /dev/null
+++ b/java/com/android/incallui/incall/impl/res/drawable/ic_sim_change_white.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/ic_sim_change_white"
+ android:oneshot="true">
+ <item
+ android:drawable="@drawable/ic_sim_change_white_00"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_01"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_02"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_03"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_04"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_05"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_06"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_07"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_08"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_09"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_10"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_11"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_12"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_13"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_14"
+ android:duration="33"/>
+ <item
+ android:drawable="@drawable/ic_sim_change_white_00"
+ android:duration="33"/>
+</animation-list> \ No newline at end of file