summaryrefslogtreecommitdiff
path: root/java/com/android
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2017-12-22 18:44:31 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-12-22 18:44:31 +0000
commit88518503c1351ba86f503ebd8742d6b292928ddd (patch)
tree97c6b6429cd3a0276ece3bba0ce022e4c6b92866 /java/com/android
parente2da6ef8a56bd9f7eedfa1c6d89e968590e0c09b (diff)
parent1e8275f3e6f57f285900ce35946064e0550b174a (diff)
Merge changes I66342431,I5e579f11,I927711aa,Idd4cc115,If8cdbdfa, ...
* changes: Automated rollback of changelist 179615699 Automated rollback of changelist 179847039 Differentiate read/unread voicemails in the NUI Voicemail by bolding. Use CHAR_TO_KEY_MAPS in DialpadCharMappings in SmartDialMaps. Reorganize classes related to smart dial. Use the orientation obtained in onFinishInflate as the truth in DialpadView. Added context menu for favorite contacts in new speed dial. Update assisted dialing extras in preparation for platform implementation. Quick fix for bugs on simulator voice call. Fixed crash in UiListener when launching activity with screen off. Handle contacts which have been disassociated with a number in Cp2PhoneLookup. Fixed crash in PinnedShortcuts. Bug: 70402588 Added copySubMessage method to PhoneLookup interface. Bubble v2 changes. Always have hardware acceration enabled for InCallActivity Include inserted calls for consideration in PhoneLookupDataSource. Don't use phone number in spam call notifications Register content observer when voicemail table changes. Add SmartDialMaps for the Bulgarian alphabet and the Ukrainian alphabet. Remove voicemail from UI only after delete request. Bubble v2 RTL language fixes. Implemented SpeedDialEntry Room Database.
Diffstat (limited to 'java/com/android')
-rw-r--r--java/com/android/bubble/res/values-car/values.xml6
-rw-r--r--java/com/android/dialer/app/DialtactsActivity.java4
-rw-r--r--java/com/android/dialer/app/list/SmartDialNumberListAdapter.java6
-rw-r--r--java/com/android/dialer/app/list/SmartDialSearchFragment.java2
-rw-r--r--java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java36
-rw-r--r--java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java25
-rw-r--r--java/com/android/dialer/calllog/ui/NewCallLogFragment.java6
-rw-r--r--java/com/android/dialer/common/concurrent/UiListener.java8
-rw-r--r--java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java14
-rw-r--r--java/com/android/dialer/database/DialerDatabaseHelper.java4
-rw-r--r--java/com/android/dialer/dialpadview/DialpadCharMappings.java17
-rw-r--r--java/com/android/dialer/dialpadview/DialpadView.java29
-rw-r--r--java/com/android/dialer/function/BiConsumer.java24
-rw-r--r--java/com/android/dialer/main/impl/MainPagerAdapter.java4
-rw-r--r--java/com/android/dialer/phonelookup/PhoneLookup.java6
-rw-r--r--java/com/android/dialer/phonelookup/composite/CompositePhoneLookup.java10
-rw-r--r--java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java107
-rw-r--r--java/com/android/dialer/precall/impl/AssistedDialAction.java6
-rw-r--r--java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java2
-rw-r--r--java/com/android/dialer/shortcuts/PinnedShortcuts.java9
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorDialogFragment.java3
-rw-r--r--java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java3
-rw-r--r--java/com/android/dialer/smartdial/RussianSmartDialMap.java94
-rw-r--r--java/com/android/dialer/smartdial/SmartDialCursorLoader.java (renamed from java/com/android/dialer/dialpadview/SmartDialCursorLoader.java)4
-rw-r--r--java/com/android/dialer/smartdial/map/BulgarianSmartDialMap.java49
-rw-r--r--java/com/android/dialer/smartdial/map/CompositeSmartDialMap.java (renamed from java/com/android/dialer/smartdial/CompositeSmartDialMap.java)16
-rw-r--r--java/com/android/dialer/smartdial/map/LatinSmartDialMap.java (renamed from java/com/android/dialer/smartdial/LatinSmartDialMap.java)43
-rw-r--r--java/com/android/dialer/smartdial/map/RussianSmartDialMap.java49
-rw-r--r--java/com/android/dialer/smartdial/map/SmartDialMap.java (renamed from java/com/android/dialer/smartdial/SmartDialMap.java)2
-rw-r--r--java/com/android/dialer/smartdial/map/UkrainianSmartDialMap.java48
-rw-r--r--java/com/android/dialer/smartdial/util/SmartDialMatchPosition.java (renamed from java/com/android/dialer/smartdial/SmartDialMatchPosition.java)6
-rw-r--r--java/com/android/dialer/smartdial/util/SmartDialNameMatcher.java (renamed from java/com/android/dialer/smartdial/SmartDialNameMatcher.java)5
-rw-r--r--java/com/android/dialer/smartdial/util/SmartDialPrefix.java (renamed from java/com/android/dialer/smartdial/SmartDialPrefix.java)3
-rw-r--r--java/com/android/dialer/telecom/TelecomUtil.java10
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java23
-rw-r--r--java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java22
-rw-r--r--java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java5
-rw-r--r--java/com/android/dialer/voicemail/model/VoicemailEntry.java7
-rw-r--r--java/com/android/incallui/AndroidManifest.xml3
-rw-r--r--java/com/android/incallui/NewReturnToCallController.java43
-rw-r--r--java/com/android/incallui/call/DialerCall.java43
-rw-r--r--java/com/android/incallui/contactgrid/TopRow.java2
-rw-r--r--java/com/android/incallui/spam/SpamCallListListener.java2
-rw-r--r--java/com/android/newbubble/NewBubble.java17
-rw-r--r--java/com/android/newbubble/res/layout/new_bubble_base.xml1
45 files changed, 572 insertions, 256 deletions
diff --git a/java/com/android/bubble/res/values-car/values.xml b/java/com/android/bubble/res/values-car/values.xml
index cf8839a84..47f20a1bf 100644
--- a/java/com/android/bubble/res/values-car/values.xml
+++ b/java/com/android/bubble/res/values-car/values.xml
@@ -18,10 +18,8 @@
<resources>
<dimen name="bubble_size">64dp</dimen>
- <dimen name="bubble_drawer_margin">54dp</dimen>
+ <dimen name="bubble_drawer_margin">50dp</dimen>
<dimen name="bubble_drawer_padding_start">38dp</dimen>
- <dimen name="bubble_drawer_padding_end">10dp</dimen>
- <dimen name="bubble_icon_padding">18dp</dimen>
- <dimen name="bubble_shadow_padding_size">18dp</dimen>
+ <dimen name="bubble_drawer_padding_end">12dp</dimen>
</resources>
diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java
index eb95a4ee4..bbb45943a 100644
--- a/java/com/android/dialer/app/DialtactsActivity.java
+++ b/java/com/android/dialer/app/DialtactsActivity.java
@@ -133,8 +133,8 @@ import com.android.dialer.searchfragment.list.NewSearchFragment;
import com.android.dialer.searchfragment.list.NewSearchFragment.SearchFragmentListener;
import com.android.dialer.simulator.Simulator;
import com.android.dialer.simulator.SimulatorComponent;
-import com.android.dialer.smartdial.SmartDialNameMatcher;
-import com.android.dialer.smartdial.SmartDialPrefix;
+import com.android.dialer.smartdial.util.SmartDialNameMatcher;
+import com.android.dialer.smartdial.util.SmartDialPrefix;
import com.android.dialer.storage.StorageComponent;
import com.android.dialer.telecom.TelecomUtil;
import com.android.dialer.util.DialerUtils;
diff --git a/java/com/android/dialer/app/list/SmartDialNumberListAdapter.java b/java/com/android/dialer/app/list/SmartDialNumberListAdapter.java
index 5b48ccfd0..1d2cda3ea 100644
--- a/java/com/android/dialer/app/list/SmartDialNumberListAdapter.java
+++ b/java/com/android/dialer/app/list/SmartDialNumberListAdapter.java
@@ -22,9 +22,9 @@ import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import com.android.contacts.common.list.ContactListItemView;
import com.android.dialer.common.LogUtil;
-import com.android.dialer.dialpadview.SmartDialCursorLoader;
-import com.android.dialer.smartdial.SmartDialMatchPosition;
-import com.android.dialer.smartdial.SmartDialNameMatcher;
+import com.android.dialer.smartdial.SmartDialCursorLoader;
+import com.android.dialer.smartdial.util.SmartDialMatchPosition;
+import com.android.dialer.smartdial.util.SmartDialNameMatcher;
import com.android.dialer.util.CallUtil;
import java.util.ArrayList;
diff --git a/java/com/android/dialer/app/list/SmartDialSearchFragment.java b/java/com/android/dialer/app/list/SmartDialSearchFragment.java
index e97a16c19..1a7f19515 100644
--- a/java/com/android/dialer/app/list/SmartDialSearchFragment.java
+++ b/java/com/android/dialer/app/list/SmartDialSearchFragment.java
@@ -31,7 +31,7 @@ import com.android.dialer.app.R;
import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.common.LogUtil;
import com.android.dialer.database.DialerDatabaseHelper;
-import com.android.dialer.dialpadview.SmartDialCursorLoader;
+import com.android.dialer.smartdial.SmartDialCursorLoader;
import com.android.dialer.util.PermissionsUtil;
import com.android.dialer.widget.EmptyContentView;
import java.util.Arrays;
diff --git a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java
index fbb58312a..042ff30a2 100644
--- a/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java
+++ b/java/com/android/dialer/calllog/datasources/phonelookup/PhoneLookupDataSource.java
@@ -110,7 +110,9 @@ public final class PhoneLookupDataSource implements CallLogDataSource {
* <p>This method uses the following algorithm:
*
* <ul>
- * <li>Selects the distinct DialerPhoneNumbers from the AnnotatedCallLog
+ * <li>Finds the phone numbers of interest by taking the union of the distinct
+ * DialerPhoneNumbers from the AnnotatedCallLog and the pending inserts provided in {@code
+ * mutations}
* <li>Uses them to fetch the current information from PhoneLookupHistory, in order to construct
* a map from DialerPhoneNumber to PhoneLookupInfo
* <ul>
@@ -137,9 +139,10 @@ public final class PhoneLookupDataSource implements CallLogDataSource {
phoneLookupHistoryRowsToUpdate.clear();
phoneLookupHistoryRowsToDelete.clear();
- // First query information from annotated call log.
+ // First query information from annotated call log (and include pending inserts).
ListenableFuture<Map<DialerPhoneNumber, Set<Long>>> annotatedCallLogIdsByNumberFuture =
- backgroundExecutorService.submit(() -> queryIdAndNumberFromAnnotatedCallLog(appContext));
+ backgroundExecutorService.submit(
+ () -> collectIdAndNumberFromAnnotatedCallLogAndPendingInserts(appContext, mutations));
// Use it to create the original info map.
ListenableFuture<ImmutableMap<DialerPhoneNumber, PhoneLookupInfo>> originalInfoMapFuture =
@@ -317,9 +320,28 @@ public final class PhoneLookupDataSource implements CallLogDataSource {
return numbers.build();
}
- private Map<DialerPhoneNumber, Set<Long>> queryIdAndNumberFromAnnotatedCallLog(
- Context appContext) {
+ private Map<DialerPhoneNumber, Set<Long>> collectIdAndNumberFromAnnotatedCallLogAndPendingInserts(
+ Context appContext, CallLogMutations mutations) {
Map<DialerPhoneNumber, Set<Long>> idsByNumber = new ArrayMap<>();
+ // First add any pending inserts to the map.
+ for (Entry<Long, ContentValues> entry : mutations.getInserts().entrySet()) {
+ long id = entry.getKey();
+ ContentValues insertedContentValues = entry.getValue();
+ DialerPhoneNumber dialerPhoneNumber;
+ try {
+ dialerPhoneNumber =
+ DialerPhoneNumber.parseFrom(
+ insertedContentValues.getAsByteArray(AnnotatedCallLog.NUMBER));
+ } catch (InvalidProtocolBufferException e) {
+ throw new IllegalStateException(e);
+ }
+ Set<Long> ids = idsByNumber.get(dialerPhoneNumber);
+ if (ids == null) {
+ ids = new ArraySet<>();
+ idsByNumber.put(dialerPhoneNumber, ids);
+ }
+ ids.add(id);
+ }
try (Cursor cursor =
appContext
@@ -332,7 +354,9 @@ public final class PhoneLookupDataSource implements CallLogDataSource {
null)) {
if (cursor == null) {
- LogUtil.e("PhoneLookupDataSource.queryIdAndNumberFromAnnotatedCallLog", "null cursor");
+ LogUtil.e(
+ "PhoneLookupDataSource.collectIdAndNumberFromAnnotatedCallLogAndPendingInserts",
+ "null cursor");
return ImmutableMap.of();
}
diff --git a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
index 0ed185966..95fbf9d04 100644
--- a/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
+++ b/java/com/android/dialer/calllog/datasources/systemcalllog/SystemCallLogDataSource.java
@@ -27,6 +27,7 @@ import android.os.Build;
import android.os.Handler;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
+import android.provider.VoicemailContract;
import android.support.annotation.ColorInt;
import android.support.annotation.MainThread;
import android.support.annotation.Nullable;
@@ -92,13 +93,21 @@ public class SystemCallLogDataSource implements CallLogDataSource {
}
// TODO(zachh): Need to somehow register observers if user enables permission after launch?
+ CallLogObserver callLogObserver =
+ new CallLogObserver(ThreadUtil.getUiThreadHandler(), appContext, contentObserverCallbacks);
+
appContext
.getContentResolver()
- .registerContentObserver(
- CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL,
- true,
- new CallLogObserver(
- ThreadUtil.getUiThreadHandler(), appContext, contentObserverCallbacks));
+ .registerContentObserver(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL, true, callLogObserver);
+
+ if (!PermissionsUtil.hasAddVoicemailPermissions(appContext)) {
+ LogUtil.i("SystemCallLogDataSource.registerContentObservers", "no add voicemail permissions");
+ return;
+ }
+ // TODO(uabdullah): Need to somehow register observers if user enables permission after launch?
+ appContext
+ .getContentResolver()
+ .registerContentObserver(VoicemailContract.Status.CONTENT_URI, true, callLogObserver);
}
@Override
@@ -462,7 +471,11 @@ public class SystemCallLogDataSource implements CallLogDataSource {
@Override
public void onChange(boolean selfChange, Uri uri) {
Assert.isMainThread();
- LogUtil.enterBlock("SystemCallLogDataSource.CallLogObserver.onChange");
+ LogUtil.i(
+ "SystemCallLogDataSource.CallLogObserver.onChange",
+ "Uri:%s, SelfChange:%b",
+ String.valueOf(uri),
+ selfChange);
super.onChange(selfChange, uri);
/*
diff --git a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
index c10b52123..719878cec 100644
--- a/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
+++ b/java/com/android/dialer/calllog/ui/NewCallLogFragment.java
@@ -58,10 +58,10 @@ public final class NewCallLogFragment extends Fragment
}
@Override
- public void onCreate(Bundle state) {
- super.onCreate(state);
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
- LogUtil.enterBlock("NewCallLogFragment.onCreate");
+ LogUtil.enterBlock("NewCallLogFragment.onActivityCreated");
CallLogComponent component = CallLogComponent.get(getContext());
CallLogFramework callLogFramework = component.callLogFramework();
diff --git a/java/com/android/dialer/common/concurrent/UiListener.java b/java/com/android/dialer/common/concurrent/UiListener.java
index 9541dbc0c..df791301f 100644
--- a/java/com/android/dialer/common/concurrent/UiListener.java
+++ b/java/com/android/dialer/common/concurrent/UiListener.java
@@ -71,7 +71,10 @@ public class UiListener<OutputT> extends Fragment {
if (uiListener == null) {
LogUtil.i("UiListener.create", "creating new UiListener for " + taskId);
uiListener = new UiListener<>();
- fragmentManager.beginTransaction().add(uiListener, taskId).commit();
+ // When launching an activity with the screen off, its onSaveInstanceState() is called before
+ // its fragments are created, which means we can't use commit() and need to use
+ // commitAllowingStateLoss(). This is not a problem for UiListener which saves no state.
+ fragmentManager.beginTransaction().add(uiListener, taskId).commitAllowingStateLoss();
}
return uiListener;
}
@@ -130,6 +133,9 @@ public class UiListener<OutputT> extends Fragment {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
+ // Note: We use commitAllowingStateLoss when attaching the fragment so it may not be safe to
+ // read savedInstanceState in all situations. (But it's not anticipated that this fragment
+ // should need to rely on saved state.)
}
@Override
diff --git a/java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java b/java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java
index 6bed818da..b01689da4 100644
--- a/java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java
+++ b/java/com/android/dialer/compat/telephony/TelephonyManagerCompat.java
@@ -57,22 +57,16 @@ public class TelephonyManagerCompat {
*
* <p>This signals to the telephony platform that an outgoing call qualifies for assisted dialing.
*/
- public static final String ALLOW_ASSISTED_DIAL = "android.telecom.extra.ALLOW_ASSISTED_DIAL";
-
- // TODO(erfanian): a bug Replace with the platform/telecom constant when available.
- /**
- * Indicates that an outgoing call has undergone assisted dialing.
- *
- * <p>Unlike {@link ALLOW_ASSISTED_DIAL}, the presence of this key further indicates that a call
- * has undergone Assisted Dialing -- not just that it qualified for Assisted Dialing.
- */
- public static final String IS_ASSISTED_DIALED = "android.telecom.extra.IS_ASSISTED_DIALED";
+ public static final String USE_ASSISTED_DIALING = "android.telecom.extra.USE_ASSISTED_DIALING";
// TODO(erfanian): a bug Replace with the platform/telecom API when available.
/** Additional information relating to the assisted dialing transformation. */
public static final String ASSISTED_DIALING_EXTRAS =
"android.telecom.extra.ASSISTED_DIALING_EXTRAS";
+ /** Indicates the Connection/Call used assisted dialing. */
+ public static final int PROPERTY_ASSISTED_DIALING_USED = 0x00000200;
+
public static final String EXTRA_IS_REFRESH =
BuildCompat.isAtLeastOMR1() ? "android.telephony.extra.IS_REFRESH" : "is_refresh";
diff --git a/java/com/android/dialer/database/DialerDatabaseHelper.java b/java/com/android/dialer/database/DialerDatabaseHelper.java
index b0bd62a34..3fb87304b 100644
--- a/java/com/android/dialer/database/DialerDatabaseHelper.java
+++ b/java/com/android/dialer/database/DialerDatabaseHelper.java
@@ -42,8 +42,8 @@ import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.database.FilteredNumberContract.FilteredNumberColumns;
-import com.android.dialer.smartdial.SmartDialNameMatcher;
-import com.android.dialer.smartdial.SmartDialPrefix;
+import com.android.dialer.smartdial.util.SmartDialNameMatcher;
+import com.android.dialer.smartdial.util.SmartDialPrefix;
import com.android.dialer.util.PermissionsUtil;
import java.util.ArrayList;
import java.util.HashSet;
diff --git a/java/com/android/dialer/dialpadview/DialpadCharMappings.java b/java/com/android/dialer/dialpadview/DialpadCharMappings.java
index 03bc2e728..0bb28ae0d 100644
--- a/java/com/android/dialer/dialpadview/DialpadCharMappings.java
+++ b/java/com/android/dialer/dialpadview/DialpadCharMappings.java
@@ -147,6 +147,23 @@ public class DialpadCharMappings {
: null;
}
+ /**
+ * Returns the character-key map of the provided ISO 639-2 language code.
+ *
+ * <p>Note: this method is for implementations of {@link
+ * com.android.dialer.smartdial.map.SmartDialMap} only. {@link #getCharToKeyMap(Context)} should
+ * be used for all other purposes.
+ *
+ * <p>It is the caller's responsibility to ensure the language code is valid and a character
+ * mapping is defined for that language. Otherwise, an exception will be thrown.
+ */
+ public static SimpleArrayMap<Character, Character> getCharToKeyMap(String languageCode) {
+ SimpleArrayMap<Character, Character> charToKeyMap = CHAR_TO_KEY_MAPS.get(languageCode);
+
+ return Assert.isNotNull(
+ charToKeyMap, "No character mappings can be found for language code '%s'", languageCode);
+ }
+
/** Returns the default character-key map (the one that uses the Latin alphabet). */
public static SimpleArrayMap<Character, Character> getDefaultCharToKeyMap() {
return Latin.CHAR_TO_KEY;
diff --git a/java/com/android/dialer/dialpadview/DialpadView.java b/java/com/android/dialer/dialpadview/DialpadView.java
index 2f494e49d..7b95ba7ea 100644
--- a/java/com/android/dialer/dialpadview/DialpadView.java
+++ b/java/com/android/dialer/dialpadview/DialpadView.java
@@ -87,6 +87,7 @@ public class DialpadView extends LinearLayout {
private ViewGroup mRateContainer;
private TextView mIldCountry;
private TextView mIldRate;
+ private boolean mIsLandscapeMode;
public DialpadView(Context context) {
this(context, null);
@@ -125,6 +126,12 @@ public class DialpadView extends LinearLayout {
protected void onFinishInflate() {
super.onFinishInflate();
+ // The orientation obtained at this point should be used as the only truth for DialpadView as we
+ // observed inconsistency between configurations obtained here and in
+ // OnPreDrawListenerForKeyLayoutAdjust under rare circumstances.
+ mIsLandscapeMode =
+ (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE);
+
setupKeypad();
mDigits = (EditText) findViewById(R.id.digits);
mDelete = (ImageButton) findViewById(R.id.deleteButton);
@@ -281,7 +288,7 @@ public class DialpadView extends LinearLayout {
final DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[i]);
ViewPropertyAnimator animator = dialpadKey.animate();
- if (isLandscapeMode()) {
+ if (mIsLandscapeMode) {
// Landscape orientation requires translation along the X axis.
// For RTL locales, ensure we translate negative on the X axis.
dialpadKey.setTranslationX((mIsRtl ? -1 : 1) * mTranslateDistance);
@@ -320,7 +327,7 @@ public class DialpadView extends LinearLayout {
* @return The animation delay.
*/
private int getKeyButtonAnimationDelay(int buttonId) {
- if (isLandscapeMode()) {
+ if (mIsLandscapeMode) {
if (mIsRtl) {
if (buttonId == R.id.three) {
return KEY_FRAME_DURATION * 1;
@@ -408,7 +415,7 @@ public class DialpadView extends LinearLayout {
* @return The animation duration.
*/
private int getKeyButtonAnimationDuration(int buttonId) {
- if (isLandscapeMode()) {
+ if (mIsLandscapeMode) {
if (mIsRtl) {
if (buttonId == R.id.one
|| buttonId == R.id.four
@@ -463,10 +470,6 @@ public class DialpadView extends LinearLayout {
return 0;
}
- private boolean isLandscapeMode() {
- return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
- }
-
/**
* An {@link OnPreDrawListener} that adjusts the height/width of each key layout so that they can
* be properly aligned.
@@ -525,7 +528,7 @@ public class DialpadView extends LinearLayout {
}
private boolean shouldAdjustKeySizes() {
- return isLandscapeMode() ? shouldAdjustKeyWidths() : shouldAdjustDigitKeyHeights();
+ return mIsLandscapeMode ? shouldAdjustKeyWidths() : shouldAdjustDigitKeyHeights();
}
/**
@@ -533,7 +536,7 @@ public class DialpadView extends LinearLayout {
* device is in landscape mode.
*/
private boolean shouldAdjustKeyWidths() {
- Assert.checkState(isLandscapeMode());
+ Assert.checkState(mIsLandscapeMode);
DialpadKeyButton dialpadKeyButton = (DialpadKeyButton) findViewById(BUTTON_IDS[0]);
LinearLayout keyLayout =
@@ -556,7 +559,7 @@ public class DialpadView extends LinearLayout {
* called when the device is in portrait mode.
*/
private boolean shouldAdjustDigitKeyHeights() {
- Assert.checkState(!isLandscapeMode());
+ Assert.checkState(!mIsLandscapeMode);
DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(BUTTON_IDS[0]);
LinearLayout keyLayout = (LinearLayout) dialpadKey.findViewById(R.id.dialpad_key_layout);
@@ -576,7 +579,7 @@ public class DialpadView extends LinearLayout {
}
private void adjustKeySizes() {
- if (isLandscapeMode()) {
+ if (mIsLandscapeMode) {
adjustKeyWidths();
} else {
adjustDigitKeyHeights();
@@ -594,7 +597,7 @@ public class DialpadView extends LinearLayout {
* LinearLayout#setLayoutParams(ViewGroup.LayoutParams)}.
*/
private void adjustDigitKeyHeights() {
- Assert.checkState(!isLandscapeMode());
+ Assert.checkState(!mIsLandscapeMode);
int maxHeight = 0;
@@ -638,7 +641,7 @@ public class DialpadView extends LinearLayout {
* View#setLayoutParams(ViewGroup.LayoutParams)}.
*/
private void adjustKeyWidths() {
- Assert.checkState(isLandscapeMode());
+ Assert.checkState(mIsLandscapeMode);
int maxWidth = 0;
for (int buttonId : BUTTON_IDS) {
diff --git a/java/com/android/dialer/function/BiConsumer.java b/java/com/android/dialer/function/BiConsumer.java
new file mode 100644
index 000000000..50052210e
--- /dev/null
+++ b/java/com/android/dialer/function/BiConsumer.java
@@ -0,0 +1,24 @@
+/*
+ * 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.function;
+
+/** Functional interface for consuming two generic values. */
+public interface BiConsumer<T, U> {
+
+ /** Consumes a value. */
+ void accept(T t, U u);
+}
diff --git a/java/com/android/dialer/main/impl/MainPagerAdapter.java b/java/com/android/dialer/main/impl/MainPagerAdapter.java
index 2d224f69c..d294640ee 100644
--- a/java/com/android/dialer/main/impl/MainPagerAdapter.java
+++ b/java/com/android/dialer/main/impl/MainPagerAdapter.java
@@ -20,7 +20,7 @@ import android.content.Context;
import android.support.annotation.IntDef;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentStatePagerAdapter;
+import android.support.v4.app.FragmentPagerAdapter;
import com.android.dialer.calllog.ui.NewCallLogFragment;
import com.android.dialer.common.Assert;
import com.android.dialer.voicemail.listui.NewVoicemailFragment;
@@ -28,7 +28,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** Adapter for {@link MainActivity} ViewPager. */
-final class MainPagerAdapter extends FragmentStatePagerAdapter {
+final class MainPagerAdapter extends FragmentPagerAdapter {
@Retention(RetentionPolicy.SOURCE)
@IntDef({
diff --git a/java/com/android/dialer/phonelookup/PhoneLookup.java b/java/com/android/dialer/phonelookup/PhoneLookup.java
index eeab4dadd..bb14c1ff6 100644
--- a/java/com/android/dialer/phonelookup/PhoneLookup.java
+++ b/java/com/android/dialer/phonelookup/PhoneLookup.java
@@ -62,6 +62,12 @@ public interface PhoneLookup {
ImmutableMap<DialerPhoneNumber, PhoneLookupInfo> existingInfoMap);
/**
+ * Populates the sub-message that this {@link PhoneLookup} is responsible for by copying the
+ * sub-message value from {@code source} to {@code destination}
+ */
+ void copySubMessage(PhoneLookupInfo.Builder destination, PhoneLookupInfo source);
+
+ /**
* Called when the results of the {@link #getMostRecentPhoneLookupInfo(ImmutableMap)} have been
* applied by the caller.
*
diff --git a/java/com/android/dialer/phonelookup/composite/CompositePhoneLookup.java b/java/com/android/dialer/phonelookup/composite/CompositePhoneLookup.java
index ee2244615..bb7856fff 100644
--- a/java/com/android/dialer/phonelookup/composite/CompositePhoneLookup.java
+++ b/java/com/android/dialer/phonelookup/composite/CompositePhoneLookup.java
@@ -112,14 +112,15 @@ public final class CompositePhoneLookup implements PhoneLookup {
ImmutableMap.builder();
for (DialerPhoneNumber dialerPhoneNumber : existingInfoMap.keySet()) {
PhoneLookupInfo.Builder combinedInfo = PhoneLookupInfo.newBuilder();
- for (ImmutableMap<DialerPhoneNumber, PhoneLookupInfo> map : allMaps) {
+ for (int i = 0; i < allMaps.size(); i++) {
+ ImmutableMap<DialerPhoneNumber, PhoneLookupInfo> map = allMaps.get(i);
PhoneLookupInfo subInfo = map.get(dialerPhoneNumber);
if (subInfo == null) {
throw new IllegalStateException(
"A sublookup didn't return an info for number: "
+ LogUtil.sanitizePhoneNumber(dialerPhoneNumber.getRawInput().getNumber()));
}
- combinedInfo.mergeFrom(subInfo);
+ phoneLookups.get(i).copySubMessage(combinedInfo, subInfo);
}
combinedMap.put(dialerPhoneNumber, combinedInfo.build());
}
@@ -129,6 +130,11 @@ public final class CompositePhoneLookup implements PhoneLookup {
}
@Override
+ public void copySubMessage(PhoneLookupInfo.Builder destination, PhoneLookupInfo source) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public ListenableFuture<Void> onSuccessfulBulkUpdate() {
List<ListenableFuture<Void>> futures = new ArrayList<>();
for (PhoneLookup phoneLookup : phoneLookups) {
diff --git a/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java b/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java
index b31d0e72e..a477e035c 100644
--- a/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java
+++ b/java/com/android/dialer/phonelookup/cp2/Cp2PhoneLookup.java
@@ -36,6 +36,7 @@ import com.android.dialer.phonelookup.PhoneLookup;
import com.android.dialer.phonelookup.PhoneLookupInfo;
import com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info;
import com.android.dialer.phonelookup.PhoneLookupInfo.Cp2Info.Cp2ContactInfo;
+import com.android.dialer.phonelookup.database.contract.PhoneLookupHistoryContract.PhoneLookupHistory;
import com.android.dialer.phonenumberproto.DialerPhoneNumberUtil;
import com.android.dialer.storage.Unencrypted;
import com.android.dialer.telecom.TelecomCallUtil;
@@ -45,6 +46,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import com.google.protobuf.InvalidProtocolBufferException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
@@ -131,8 +133,25 @@ public final class Cp2PhoneLookup implements PhoneLookup {
private boolean isDirtyInternal(ImmutableSet<DialerPhoneNumber> phoneNumbers) {
long lastModified = sharedPreferences.getLong(PREF_LAST_TIMESTAMP_PROCESSED, 0L);
- return contactsUpdated(queryPhoneTableForContactIds(phoneNumbers), lastModified)
- || contactsDeleted(lastModified);
+ // We are always going to need to do this check and it is pretty cheap so do it first.
+ if (anyContactsDeletedSince(lastModified)) {
+ return true;
+ }
+ // Hopefully the most common case is there are no contacts updated; we can detect this cheaply.
+ if (noContactsModifiedSince(lastModified)) {
+ return false;
+ }
+ // This method is more expensive but is probably the most likely scenario; we are looking for
+ // changes to contacts which have been called.
+ if (contactsUpdated(queryPhoneTableForContactIds(phoneNumbers), lastModified)) {
+ return true;
+ }
+ // This is the most expensive method so do it last; the scenario is that a contact which has
+ // been called got disassociated with a number and we need to clear their information.
+ if (contactsUpdated(queryPhoneLookupHistoryForContactIds(), lastModified)) {
+ return true;
+ }
+ return false;
}
/**
@@ -155,6 +174,46 @@ public final class Cp2PhoneLookup implements PhoneLookup {
return contactIds;
}
+ /** Gets all of the contact ids from PhoneLookupHistory. */
+ private Set<Long> queryPhoneLookupHistoryForContactIds() {
+ Set<Long> contactIds = new ArraySet<>();
+ try (Cursor cursor =
+ appContext
+ .getContentResolver()
+ .query(
+ PhoneLookupHistory.CONTENT_URI,
+ new String[] {
+ PhoneLookupHistory.PHONE_LOOKUP_INFO,
+ },
+ null,
+ null,
+ null)) {
+
+ if (cursor == null) {
+ LogUtil.w("Cp2PhoneLookup.queryPhoneLookupHistoryForContactIds", "null cursor");
+ return contactIds;
+ }
+
+ if (cursor.moveToFirst()) {
+ int phoneLookupInfoColumn =
+ cursor.getColumnIndexOrThrow(PhoneLookupHistory.PHONE_LOOKUP_INFO);
+ do {
+ PhoneLookupInfo phoneLookupInfo;
+ try {
+ phoneLookupInfo = PhoneLookupInfo.parseFrom(cursor.getBlob(phoneLookupInfoColumn));
+ } catch (InvalidProtocolBufferException e) {
+ throw new IllegalStateException(e);
+ }
+ for (Cp2ContactInfo info : phoneLookupInfo.getCp2Info().getCp2ContactInfoList()) {
+ contactIds.add(info.getContactId());
+ }
+ } while (cursor.moveToNext());
+ }
+ }
+
+ return contactIds;
+ }
+
private Set<Long> queryPhoneTableForContactIdsBasedOnE164(Set<String> validE164Numbers) {
Set<Long> contactIds = new ArraySet<>();
if (validE164Numbers.isEmpty()) {
@@ -226,8 +285,26 @@ public final class Cp2PhoneLookup implements PhoneLookup {
null);
}
+ private boolean noContactsModifiedSince(long lastModified) {
+ try (Cursor cursor =
+ appContext
+ .getContentResolver()
+ .query(
+ Contacts.CONTENT_URI,
+ new String[] {Contacts._ID},
+ Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + " > ?",
+ new String[] {Long.toString(lastModified)},
+ Contacts._ID + " limit 1")) {
+ if (cursor == null) {
+ LogUtil.w("Cp2PhoneLookup.noContactsModifiedSince", "null cursor");
+ return false;
+ }
+ return cursor.getCount() == 0;
+ }
+ }
+
/** Returns true if any contacts were deleted after {@code lastModified}. */
- private boolean contactsDeleted(long lastModified) {
+ private boolean anyContactsDeletedSince(long lastModified) {
try (Cursor cursor =
appContext
.getContentResolver()
@@ -236,9 +313,9 @@ public final class Cp2PhoneLookup implements PhoneLookup {
new String[] {DeletedContacts.CONTACT_DELETED_TIMESTAMP},
DeletedContacts.CONTACT_DELETED_TIMESTAMP + " > ?",
new String[] {Long.toString(lastModified)},
- null)) {
+ DeletedContacts.CONTACT_DELETED_TIMESTAMP + " limit 1")) {
if (cursor == null) {
- LogUtil.w("Cp2PhoneLookup.contactsDeleted", "null cursor");
+ LogUtil.w("Cp2PhoneLookup.anyContactsDeletedSince", "null cursor");
return false;
}
return cursor.getCount() > 0;
@@ -253,6 +330,11 @@ public final class Cp2PhoneLookup implements PhoneLookup {
() -> getMostRecentPhoneLookupInfoInternal(existingInfoMap));
}
+ @Override
+ public void copySubMessage(PhoneLookupInfo.Builder destination, PhoneLookupInfo source) {
+ destination.setCp2Info(source.getCp2Info());
+ }
+
private ImmutableMap<DialerPhoneNumber, PhoneLookupInfo> getMostRecentPhoneLookupInfoInternal(
ImmutableMap<DialerPhoneNumber, PhoneLookupInfo> existingInfoMap) {
currentLastTimestampProcessed = null;
@@ -407,6 +489,11 @@ public final class Cp2PhoneLookup implements PhoneLookup {
partitionedNumbers.dialerPhoneNumbersForE164(e164Number);
Cp2ContactInfo info = buildCp2ContactInfoFromPhoneCursor(appContext, cursor);
addInfo(map, dialerPhoneNumbers, info);
+
+ // We are going to remove the numbers that we've handled so that we later can detect
+ // numbers that weren't handled and therefore need to have their contact information
+ // removed.
+ updatedNumbers.removeAll(dialerPhoneNumbers);
}
}
}
@@ -424,10 +511,20 @@ public final class Cp2PhoneLookup implements PhoneLookup {
partitionedNumbers.dialerPhoneNumbersForUnformattable(unformattableNumber);
Cp2ContactInfo info = buildCp2ContactInfoFromPhoneCursor(appContext, cursor);
addInfo(map, dialerPhoneNumbers, info);
+
+ // We are going to remove the numbers that we've handled so that we later can detect
+ // numbers that weren't handled and therefore need to have their contact information
+ // removed.
+ updatedNumbers.removeAll(dialerPhoneNumbers);
}
}
}
}
+ // The leftovers in updatedNumbers that weren't removed are numbers that were previously
+ // associated with contacts, but are no longer. Remove the contact information for them.
+ for (DialerPhoneNumber dialerPhoneNumber : updatedNumbers) {
+ map.put(dialerPhoneNumber, ImmutableSet.of());
+ }
return map;
}
diff --git a/java/com/android/dialer/precall/impl/AssistedDialAction.java b/java/com/android/dialer/precall/impl/AssistedDialAction.java
index c4f61d2dd..dc2510960 100644
--- a/java/com/android/dialer/precall/impl/AssistedDialAction.java
+++ b/java/com/android/dialer/precall/impl/AssistedDialAction.java
@@ -51,10 +51,12 @@ public class AssistedDialAction implements PreCallAction {
AssistedDialingMediator assistedDialingMediator =
ConcreteCreator.createNewAssistedDialingMediator(
context.getSystemService(TelephonyManager.class), context);
+ if (Build.VERSION.SDK_INT > ConcreteCreator.BUILD_CODE_CEILING) {
+ builder.getOutgoingCallExtras().putBoolean(TelephonyManagerCompat.USE_ASSISTED_DIALING, true);
+ }
if (!assistedDialingMediator.isPlatformEligible()) {
return;
}
- builder.getOutgoingCallExtras().putBoolean(TelephonyManagerCompat.ALLOW_ASSISTED_DIAL, true);
String phoneNumber =
builder.getUri().getScheme().equals(PhoneAccount.SCHEME_TEL)
? builder.getUri().getSchemeSpecificPart()
@@ -62,8 +64,8 @@ public class AssistedDialAction implements PreCallAction {
Optional<TransformationInfo> transformedNumber =
assistedDialingMediator.attemptAssistedDial(phoneNumber);
if (transformedNumber.isPresent()) {
+ builder.getOutgoingCallExtras().putBoolean(TelephonyManagerCompat.USE_ASSISTED_DIALING, true);
Bundle assistedDialingExtras = transformedNumber.get().toBundle();
- builder.getOutgoingCallExtras().putBoolean(TelephonyManagerCompat.IS_ASSISTED_DIALED, true);
builder
.getOutgoingCallExtras()
.putBundle(TelephonyManagerCompat.ASSISTED_DIALING_EXTRAS, assistedDialingExtras);
diff --git a/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
index 23e3f9d88..23f368f54 100644
--- a/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
+++ b/java/com/android/dialer/searchfragment/cp2/SearchContactsCursorLoader.java
@@ -28,9 +28,9 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.android.contacts.common.preference.ContactsPreferences;
-import com.android.dialer.dialpadview.SmartDialCursorLoader;
import com.android.dialer.searchfragment.common.Projections;
import com.android.dialer.searchfragment.common.SearchCursor;
+import com.android.dialer.smartdial.SmartDialCursorLoader;
/** Cursor Loader for CP2 contacts. */
public final class SearchContactsCursorLoader extends CursorLoader {
diff --git a/java/com/android/dialer/shortcuts/PinnedShortcuts.java b/java/com/android/dialer/shortcuts/PinnedShortcuts.java
index bfcc3df81..6e23a5c21 100644
--- a/java/com/android/dialer/shortcuts/PinnedShortcuts.java
+++ b/java/com/android/dialer/shortcuts/PinnedShortcuts.java
@@ -46,7 +46,6 @@ import java.util.Map;
* <p>When refreshing pinned shortcuts, we check to make sure that pinned contact information is
* still up to date (e.g. photo and name). We also check to see if the contact has been deleted from
* the user's contacts, and if so, we disable the pinned shortcut.
- *
*/
@TargetApi(VERSION_CODES.N_MR1) // Shortcuts introduced in N MR1
final class PinnedShortcuts {
@@ -107,6 +106,14 @@ final class PinnedShortcuts {
// setRank is nonsensical for pinned shortcuts and therefore could not be calculated.
continue;
}
+ // Exclude shortcuts like the "Phone NUI" shortcut.
+ String action = null;
+ if (shortcutInfo.getIntent() != null) {
+ action = shortcutInfo.getIntent().getAction();
+ }
+ if (action == null || !action.equals("com.android.dialer.shortcuts.CALL_CONTACT")) {
+ continue;
+ }
String lookupKey = DialerShortcut.getLookupKeyFromShortcutInfo(shortcutInfo);
Uri lookupUri = DialerShortcut.getLookupUriFromShortcutInfo(shortcutInfo);
diff --git a/java/com/android/dialer/simulator/impl/SimulatorDialogFragment.java b/java/com/android/dialer/simulator/impl/SimulatorDialogFragment.java
index f8403c7fe..96ea62739 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorDialogFragment.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorDialogFragment.java
@@ -29,7 +29,7 @@ public final class SimulatorDialogFragment extends DialogFragment {
private final String[] callerIdPresentationItems = {
"ALLOWED", "PAYPHONE", "RESTRICTED", "UNKNOWN"
};
- private int callerIdPresentationChoice;
+ private int callerIdPresentationChoice = 1;
private DialogCallback dialogCallback;
@@ -47,6 +47,7 @@ public final class SimulatorDialogFragment extends DialogFragment {
public Dialog onCreateDialog(Bundle bundle) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
final EditText input = new EditText(getActivity());
+ input.setHint("Please input phone number");
builder
.setTitle("Phone Number:")
.setView(input)
diff --git a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
index 89c5d2f14..ff00dd87e 100644
--- a/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
+++ b/java/com/android/dialer/simulator/impl/SimulatorVoiceCall.java
@@ -120,7 +120,8 @@ final class SimulatorVoiceCall
private void addSpamIncomingCall() {
String callerId = "+1-661-778-3020"; /* Blacklisted custom spam number */
- SimulatorSimCallManager.addNewIncomingCall(context, callerId, false /* isVideo */);
+ connectionTag =
+ SimulatorSimCallManager.addNewIncomingCall(context, callerId, false /* isVideo */);
}
private void addNewEmergencyCallBack() {
diff --git a/java/com/android/dialer/smartdial/RussianSmartDialMap.java b/java/com/android/dialer/smartdial/RussianSmartDialMap.java
deleted file mode 100644
index ada9182e1..000000000
--- a/java/com/android/dialer/smartdial/RussianSmartDialMap.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.smartdial;
-
-import android.support.v4.util.SimpleArrayMap;
-import com.google.common.base.Optional;
-
-/** A {@link SmartDialMap} for the Russian alphabet. */
-@SuppressWarnings("Guava")
-final class RussianSmartDialMap extends SmartDialMap {
- private static final SimpleArrayMap<Character, Character> CHAR_TO_KEY_MAP =
- new SimpleArrayMap<>();
-
- // Reference: https://en.wikipedia.org/wiki/Russian_alphabet
- static {
- CHAR_TO_KEY_MAP.put('а', '2');
- CHAR_TO_KEY_MAP.put('б', '2');
- CHAR_TO_KEY_MAP.put('в', '2');
- CHAR_TO_KEY_MAP.put('г', '2');
-
- CHAR_TO_KEY_MAP.put('д', '3');
- CHAR_TO_KEY_MAP.put('е', '3');
- CHAR_TO_KEY_MAP.put('ё', '3');
- CHAR_TO_KEY_MAP.put('ж', '3');
- CHAR_TO_KEY_MAP.put('з', '3');
-
- CHAR_TO_KEY_MAP.put('и', '4');
- CHAR_TO_KEY_MAP.put('й', '4');
- CHAR_TO_KEY_MAP.put('к', '4');
- CHAR_TO_KEY_MAP.put('л', '4');
-
- CHAR_TO_KEY_MAP.put('м', '5');
- CHAR_TO_KEY_MAP.put('н', '5');
- CHAR_TO_KEY_MAP.put('о', '5');
- CHAR_TO_KEY_MAP.put('п', '5');
-
- CHAR_TO_KEY_MAP.put('р', '6');
- CHAR_TO_KEY_MAP.put('с', '6');
- CHAR_TO_KEY_MAP.put('т', '6');
- CHAR_TO_KEY_MAP.put('у', '6');
-
- CHAR_TO_KEY_MAP.put('ф', '7');
- CHAR_TO_KEY_MAP.put('х', '7');
- CHAR_TO_KEY_MAP.put('ц', '7');
- CHAR_TO_KEY_MAP.put('ч', '7');
-
- CHAR_TO_KEY_MAP.put('ш', '8');
- CHAR_TO_KEY_MAP.put('щ', '8');
- CHAR_TO_KEY_MAP.put('ъ', '8');
- CHAR_TO_KEY_MAP.put('ы', '8');
-
- CHAR_TO_KEY_MAP.put('ь', '9');
- CHAR_TO_KEY_MAP.put('э', '9');
- CHAR_TO_KEY_MAP.put('ю', '9');
- CHAR_TO_KEY_MAP.put('я', '9');
- }
-
- private static RussianSmartDialMap instance;
-
- static RussianSmartDialMap getInstance() {
- if (instance == null) {
- instance = new RussianSmartDialMap();
- }
-
- return instance;
- }
-
- private RussianSmartDialMap() {}
-
- @Override
- Optional<Character> normalizeCharacter(char ch) {
- ch = Character.toLowerCase(ch);
- return isValidDialpadAlphabeticChar(ch) ? Optional.of(ch) : Optional.absent();
- }
-
- @Override
- SimpleArrayMap<Character, Character> getCharToKeyMap() {
- return CHAR_TO_KEY_MAP;
- }
-}
diff --git a/java/com/android/dialer/dialpadview/SmartDialCursorLoader.java b/java/com/android/dialer/smartdial/SmartDialCursorLoader.java
index d085b55bd..f6bc9325a 100644
--- a/java/com/android/dialer/dialpadview/SmartDialCursorLoader.java
+++ b/java/com/android/dialer/smartdial/SmartDialCursorLoader.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.dialer.dialpadview;
+package com.android.dialer.smartdial;
import android.content.AsyncTaskLoader;
import android.content.Context;
@@ -25,7 +25,7 @@ import com.android.dialer.common.LogUtil;
import com.android.dialer.database.Database;
import com.android.dialer.database.DialerDatabaseHelper;
import com.android.dialer.database.DialerDatabaseHelper.ContactNumber;
-import com.android.dialer.smartdial.SmartDialNameMatcher;
+import com.android.dialer.smartdial.util.SmartDialNameMatcher;
import com.android.dialer.util.PermissionsUtil;
import java.util.ArrayList;
diff --git a/java/com/android/dialer/smartdial/map/BulgarianSmartDialMap.java b/java/com/android/dialer/smartdial/map/BulgarianSmartDialMap.java
new file mode 100644
index 000000000..5be9761a1
--- /dev/null
+++ b/java/com/android/dialer/smartdial/map/BulgarianSmartDialMap.java
@@ -0,0 +1,49 @@
+/*
+ * 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.smartdial.map;
+
+import android.support.v4.util.SimpleArrayMap;
+import com.android.dialer.dialpadview.DialpadCharMappings;
+import com.google.common.base.Optional;
+
+/** A {@link SmartDialMap} for the Bulgarian alphabet. */
+@SuppressWarnings("Guava")
+final class BulgarianSmartDialMap extends SmartDialMap {
+
+ private static BulgarianSmartDialMap instance;
+
+ static BulgarianSmartDialMap getInstance() {
+ if (instance == null) {
+ instance = new BulgarianSmartDialMap();
+ }
+
+ return instance;
+ }
+
+ private BulgarianSmartDialMap() {}
+
+ @Override
+ Optional<Character> normalizeCharacter(char ch) {
+ ch = Character.toLowerCase(ch);
+ return isValidDialpadAlphabeticChar(ch) ? Optional.of(ch) : Optional.absent();
+ }
+
+ @Override
+ SimpleArrayMap<Character, Character> getCharToKeyMap() {
+ return DialpadCharMappings.getCharToKeyMap("bul");
+ }
+}
diff --git a/java/com/android/dialer/smartdial/CompositeSmartDialMap.java b/java/com/android/dialer/smartdial/map/CompositeSmartDialMap.java
index d51e46f76..df32d4ce7 100644
--- a/java/com/android/dialer/smartdial/CompositeSmartDialMap.java
+++ b/java/com/android/dialer/smartdial/map/CompositeSmartDialMap.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.dialer.smartdial;
+package com.android.dialer.smartdial.map;
import android.content.Context;
import android.support.annotation.VisibleForTesting;
@@ -45,7 +45,9 @@ public class CompositeSmartDialMap {
private static final SimpleArrayMap<String, SmartDialMap> EXTRA_MAPS = new SimpleArrayMap<>();
static {
+ EXTRA_MAPS.put("bul", BulgarianSmartDialMap.getInstance());
EXTRA_MAPS.put("rus", RussianSmartDialMap.getInstance());
+ EXTRA_MAPS.put("ukr", UkrainianSmartDialMap.getInstance());
}
private CompositeSmartDialMap() {}
@@ -56,7 +58,7 @@ public class CompositeSmartDialMap {
* <p>The provided character is expected to be a normalized character. See {@link
* SmartDialMap#normalizeCharacter(char)} for details.
*/
- static boolean isValidDialpadCharacter(Context context, char ch) {
+ public static boolean isValidDialpadCharacter(Context context, char ch) {
if (DEFAULT_MAP.isValidDialpadCharacter(ch)) {
return true;
}
@@ -71,7 +73,7 @@ public class CompositeSmartDialMap {
* <p>The provided character is expected to be a normalized character. See {@link
* SmartDialMap#normalizeCharacter(char)} for details.
*/
- static boolean isValidDialpadAlphabeticChar(Context context, char ch) {
+ public static boolean isValidDialpadAlphabeticChar(Context context, char ch) {
if (DEFAULT_MAP.isValidDialpadAlphabeticChar(ch)) {
return true;
}
@@ -83,7 +85,7 @@ public class CompositeSmartDialMap {
/**
* Returns true if the provided character is a digit, and can be mapped to a key on the dialpad.
*/
- static boolean isValidDialpadNumericChar(Context context, char ch) {
+ public static boolean isValidDialpadNumericChar(Context context, char ch) {
if (DEFAULT_MAP.isValidDialpadNumericChar(ch)) {
return true;
}
@@ -100,7 +102,7 @@ public class CompositeSmartDialMap {
*
* <p>If the provided character can't be mapped to a key on the dialpad, return -1.
*/
- static byte getDialpadIndex(Context context, char ch) {
+ public static byte getDialpadIndex(Context context, char ch) {
Optional<Byte> dialpadIndex = DEFAULT_MAP.getDialpadIndex(ch);
if (dialpadIndex.isPresent()) {
return dialpadIndex.get();
@@ -122,7 +124,7 @@ public class CompositeSmartDialMap {
*
* <p>If the provided character can't be mapped to a key on the dialpad, return the character.
*/
- static char getDialpadNumericCharacter(Context context, char ch) {
+ public static char getDialpadNumericCharacter(Context context, char ch) {
Optional<Character> dialpadNumericChar = DEFAULT_MAP.getDialpadNumericCharacter(ch);
if (dialpadNumericChar.isPresent()) {
return dialpadNumericChar.get();
@@ -142,7 +144,7 @@ public class CompositeSmartDialMap {
*
* <p>If the provided character can't be mapped to a key on the dialpad, return the character.
*/
- static char normalizeCharacter(Context context, char ch) {
+ public static char normalizeCharacter(Context context, char ch) {
Optional<Character> normalizedChar = DEFAULT_MAP.normalizeCharacter(ch);
if (normalizedChar.isPresent()) {
return normalizedChar.get();
diff --git a/java/com/android/dialer/smartdial/LatinSmartDialMap.java b/java/com/android/dialer/smartdial/map/LatinSmartDialMap.java
index b67901bbe..b8ef951c5 100644
--- a/java/com/android/dialer/smartdial/LatinSmartDialMap.java
+++ b/java/com/android/dialer/smartdial/map/LatinSmartDialMap.java
@@ -14,52 +14,15 @@
* limitations under the License.
*/
-package com.android.dialer.smartdial;
+package com.android.dialer.smartdial.map;
import android.support.v4.util.SimpleArrayMap;
+import com.android.dialer.dialpadview.DialpadCharMappings;
import com.google.common.base.Optional;
/** A {@link SmartDialMap} for the Latin alphabet, which is for T9 dialpad searching. */
@SuppressWarnings("Guava")
final class LatinSmartDialMap extends SmartDialMap {
- private static final SimpleArrayMap<Character, Character> CHAR_TO_KEY_MAP =
- new SimpleArrayMap<>();
-
- static {
- CHAR_TO_KEY_MAP.put('a', '2');
- CHAR_TO_KEY_MAP.put('b', '2');
- CHAR_TO_KEY_MAP.put('c', '2');
-
- CHAR_TO_KEY_MAP.put('d', '3');
- CHAR_TO_KEY_MAP.put('e', '3');
- CHAR_TO_KEY_MAP.put('f', '3');
-
- CHAR_TO_KEY_MAP.put('g', '4');
- CHAR_TO_KEY_MAP.put('h', '4');
- CHAR_TO_KEY_MAP.put('i', '4');
-
- CHAR_TO_KEY_MAP.put('j', '5');
- CHAR_TO_KEY_MAP.put('k', '5');
- CHAR_TO_KEY_MAP.put('l', '5');
-
- CHAR_TO_KEY_MAP.put('m', '6');
- CHAR_TO_KEY_MAP.put('n', '6');
- CHAR_TO_KEY_MAP.put('o', '6');
-
- CHAR_TO_KEY_MAP.put('p', '7');
- CHAR_TO_KEY_MAP.put('q', '7');
- CHAR_TO_KEY_MAP.put('r', '7');
- CHAR_TO_KEY_MAP.put('s', '7');
-
- CHAR_TO_KEY_MAP.put('t', '8');
- CHAR_TO_KEY_MAP.put('u', '8');
- CHAR_TO_KEY_MAP.put('v', '8');
-
- CHAR_TO_KEY_MAP.put('w', '9');
- CHAR_TO_KEY_MAP.put('x', '9');
- CHAR_TO_KEY_MAP.put('y', '9');
- CHAR_TO_KEY_MAP.put('z', '9');
- }
private static LatinSmartDialMap instance;
@@ -780,6 +743,6 @@ final class LatinSmartDialMap extends SmartDialMap {
@Override
SimpleArrayMap<Character, Character> getCharToKeyMap() {
- return CHAR_TO_KEY_MAP;
+ return DialpadCharMappings.getDefaultCharToKeyMap();
}
}
diff --git a/java/com/android/dialer/smartdial/map/RussianSmartDialMap.java b/java/com/android/dialer/smartdial/map/RussianSmartDialMap.java
new file mode 100644
index 000000000..c10bbb0ce
--- /dev/null
+++ b/java/com/android/dialer/smartdial/map/RussianSmartDialMap.java
@@ -0,0 +1,49 @@
+/*
+ * 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.smartdial.map;
+
+import android.support.v4.util.SimpleArrayMap;
+import com.android.dialer.dialpadview.DialpadCharMappings;
+import com.google.common.base.Optional;
+
+/** A {@link SmartDialMap} for the Russian alphabet. */
+@SuppressWarnings("Guava")
+final class RussianSmartDialMap extends SmartDialMap {
+
+ private static RussianSmartDialMap instance;
+
+ static RussianSmartDialMap getInstance() {
+ if (instance == null) {
+ instance = new RussianSmartDialMap();
+ }
+
+ return instance;
+ }
+
+ private RussianSmartDialMap() {}
+
+ @Override
+ Optional<Character> normalizeCharacter(char ch) {
+ ch = Character.toLowerCase(ch);
+ return isValidDialpadAlphabeticChar(ch) ? Optional.of(ch) : Optional.absent();
+ }
+
+ @Override
+ SimpleArrayMap<Character, Character> getCharToKeyMap() {
+ return DialpadCharMappings.getCharToKeyMap("rus");
+ }
+}
diff --git a/java/com/android/dialer/smartdial/SmartDialMap.java b/java/com/android/dialer/smartdial/map/SmartDialMap.java
index bc5c9ea72..c74dd2893 100644
--- a/java/com/android/dialer/smartdial/SmartDialMap.java
+++ b/java/com/android/dialer/smartdial/map/SmartDialMap.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.dialer.smartdial;
+package com.android.dialer.smartdial.map;
import android.support.v4.util.SimpleArrayMap;
import com.google.common.base.Optional;
diff --git a/java/com/android/dialer/smartdial/map/UkrainianSmartDialMap.java b/java/com/android/dialer/smartdial/map/UkrainianSmartDialMap.java
new file mode 100644
index 000000000..844732c32
--- /dev/null
+++ b/java/com/android/dialer/smartdial/map/UkrainianSmartDialMap.java
@@ -0,0 +1,48 @@
+/*
+ * 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.smartdial.map;
+
+import android.support.v4.util.SimpleArrayMap;
+import com.android.dialer.dialpadview.DialpadCharMappings;
+import com.google.common.base.Optional;
+
+/** A {@link SmartDialMap} for the Ukrainian alphabet. */
+final class UkrainianSmartDialMap extends SmartDialMap {
+
+ private static UkrainianSmartDialMap instance;
+
+ static UkrainianSmartDialMap getInstance() {
+ if (instance == null) {
+ instance = new UkrainianSmartDialMap();
+ }
+
+ return instance;
+ }
+
+ private UkrainianSmartDialMap() {}
+
+ @Override
+ Optional<Character> normalizeCharacter(char ch) {
+ ch = Character.toLowerCase(ch);
+ return isValidDialpadAlphabeticChar(ch) ? Optional.of(ch) : Optional.absent();
+ }
+
+ @Override
+ SimpleArrayMap<Character, Character> getCharToKeyMap() {
+ return DialpadCharMappings.getCharToKeyMap("ukr");
+ }
+}
diff --git a/java/com/android/dialer/smartdial/SmartDialMatchPosition.java b/java/com/android/dialer/smartdial/util/SmartDialMatchPosition.java
index 8056ad723..db317ae6b 100644
--- a/java/com/android/dialer/smartdial/SmartDialMatchPosition.java
+++ b/java/com/android/dialer/smartdial/util/SmartDialMatchPosition.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package com.android.dialer.smartdial;
+package com.android.dialer.smartdial.util;
-import android.util.Log;
+import com.android.dialer.common.LogUtil;
import java.util.ArrayList;
/**
@@ -59,7 +59,7 @@ public class SmartDialMatchPosition {
public static void print(ArrayList<SmartDialMatchPosition> list) {
for (int i = 0; i < list.size(); i++) {
SmartDialMatchPosition m = list.get(i);
- Log.d(TAG, "[" + m.start + "," + m.end + "]");
+ LogUtil.d(TAG, "[" + m.start + "," + m.end + "]");
}
}
diff --git a/java/com/android/dialer/smartdial/SmartDialNameMatcher.java b/java/com/android/dialer/smartdial/util/SmartDialNameMatcher.java
index 4e3e0cc3f..725c88c57 100644
--- a/java/com/android/dialer/smartdial/SmartDialNameMatcher.java
+++ b/java/com/android/dialer/smartdial/util/SmartDialNameMatcher.java
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-package com.android.dialer.smartdial;
+package com.android.dialer.smartdial.util;
import android.content.Context;
import android.support.annotation.Nullable;
import android.text.TextUtils;
-import com.android.dialer.smartdial.SmartDialPrefix.PhoneNumberTokens;
+import com.android.dialer.smartdial.map.CompositeSmartDialMap;
+import com.android.dialer.smartdial.util.SmartDialPrefix.PhoneNumberTokens;
import java.util.ArrayList;
/**
diff --git a/java/com/android/dialer/smartdial/SmartDialPrefix.java b/java/com/android/dialer/smartdial/util/SmartDialPrefix.java
index b9c1f8c11..9af411913 100644
--- a/java/com/android/dialer/smartdial/SmartDialPrefix.java
+++ b/java/com/android/dialer/smartdial/util/SmartDialPrefix.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.dialer.smartdial;
+package com.android.dialer.smartdial.util;
import android.content.Context;
import android.content.SharedPreferences;
@@ -22,6 +22,7 @@ import android.preference.PreferenceManager;
import android.support.annotation.VisibleForTesting;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import com.android.dialer.smartdial.map.CompositeSmartDialMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
diff --git a/java/com/android/dialer/telecom/TelecomUtil.java b/java/com/android/dialer/telecom/TelecomUtil.java
index 22f3727e6..c64a50231 100644
--- a/java/com/android/dialer/telecom/TelecomUtil.java
+++ b/java/com/android/dialer/telecom/TelecomUtil.java
@@ -178,6 +178,10 @@ public abstract class TelecomUtil {
* are not included.
*/
public static boolean isInManagedCall(Context context) {
+ return instance.isInManagedCall(context);
+ }
+
+ public static boolean isInCall(Context context) {
return instance.isInCall(context);
}
@@ -289,7 +293,7 @@ public abstract class TelecomUtil {
@VisibleForTesting()
public static class TelecomUtilImpl {
- public boolean isInCall(Context context) {
+ public boolean isInManagedCall(Context context) {
if (hasReadPhoneStatePermission(context)) {
// The TelecomManager#isInCall method returns true anytime the user is in a call.
// Starting in O, the APIs include support for self-managed ConnectionServices so that other
@@ -308,6 +312,10 @@ public abstract class TelecomUtil {
return false;
}
+ public boolean isInCall(Context context) {
+ return hasReadPhoneStatePermission(context) && getTelecomManager(context).isInCall();
+ }
+
public boolean hasPermission(Context context, String permission) {
return ContextCompat.checkSelfPermission(context, permission)
== PackageManager.PERMISSION_GRANTED;
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
index 315bf1cf0..93d5cda3e 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailAdapter.java
@@ -67,9 +67,9 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
private final Clock clock;
/** {@link Integer#MAX_VALUE} when the "Today" header should not be displayed. */
- private final int todayHeaderPosition;
+ private int todayHeaderPosition = Integer.MAX_VALUE;
/** {@link Integer#MAX_VALUE} when the "Older" header should not be displayed. */
- private final int olderHeaderPosition;
+ private int olderHeaderPosition = Integer.MAX_VALUE;
private final FragmentManager fragmentManager;
/** A valid id for {@link VoicemailEntry} is greater than 0 */
@@ -107,7 +107,15 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
this.clock = clock;
this.fragmentManager = fragmentManager;
initializeMediaPlayerListeners();
+ updateHeaderPositions();
+ }
+ private void updateHeaderPositions() {
+ LogUtil.i(
+ "NewVoicemailAdapter.updateHeaderPositions",
+ "before updating todayPos:%d, olderPos:%d",
+ todayHeaderPosition,
+ olderHeaderPosition);
// Calculate header adapter positions by reading cursor.
long currentTimeMillis = clock.currentTimeMillis();
if (cursor.moveToNext()) {
@@ -134,6 +142,11 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
this.todayHeaderPosition = Integer.MAX_VALUE;
this.olderHeaderPosition = Integer.MAX_VALUE;
}
+ LogUtil.i(
+ "NewVoicemailAdapter.updateHeaderPositions",
+ "after updating todayPos:%d, olderPos:%d",
+ todayHeaderPosition,
+ olderHeaderPosition);
}
private void initializeMediaPlayerListeners() {
@@ -143,8 +156,10 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
}
public void updateCursor(Cursor updatedCursor) {
+ LogUtil.enterBlock("NewVoicemailAdapter.updateCursor");
deletedVoicemailPosition.clear();
this.cursor = updatedCursor;
+ updateHeaderPositions();
notifyDataSetChanged();
}
@@ -509,8 +524,6 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
Assert.checkArgument(expandedViewHolder.getViewHolderVoicemailUri().equals(voicemailUri));
- notifyItemRemoved(expandedViewHolder.getAdapterPosition());
-
Assert.checkArgument(currentlyExpandedViewHolderId == expandedViewHolder.getViewHolderId());
collapseExpandedViewHolder(expandedViewHolder);
@@ -524,6 +537,8 @@ final class NewVoicemailAdapter extends RecyclerView.Adapter<ViewHolder>
.onSuccess(deleteVoicemailCallBack)
.build()
.executeSerial(new Pair<>(context, voicemailUri));
+
+ notifyItemRemoved(expandedViewHolder.getAdapterPosition());
}
private void onVoicemailDeleted(Integer integer) {
diff --git a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
index 24bed0f04..dac4ebafc 100644
--- a/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
+++ b/java/com/android/dialer/voicemail/listui/NewVoicemailViewHolder.java
@@ -21,6 +21,7 @@ import static android.view.View.VISIBLE;
import android.app.FragmentManager;
import android.content.Context;
import android.database.Cursor;
+import android.graphics.Typeface;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
@@ -124,6 +125,9 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On
transcriptionTextView.setText(voicemailTranscription);
}
+ // Bold if voicemail is unread
+ boldViewHolderIfUnread();
+
itemView.setOnClickListener(this);
menuButton.setOnClickListener(
NewVoicemailMenu.createOnClickListener(context, voicemailEntryOfViewHolder));
@@ -173,6 +177,20 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On
mediaPlayerView.getVisibility() == VISIBLE);
}
+ private void boldViewHolderIfUnread() {
+ LogUtil.v(
+ "NewVoicemailViewHolder.boldViewHolderIfUnread",
+ "id:%d, isRead:%d",
+ voicemailEntryOfViewHolder.id(),
+ voicemailEntryOfViewHolder.isRead());
+
+ if (voicemailEntryOfViewHolder.isRead() == 0) {
+ primaryTextView.setTypeface(null, Typeface.BOLD);
+ secondaryTextView.setTypeface(null, Typeface.BOLD);
+ transcriptionTextView.setTypeface(null, Typeface.BOLD);
+ }
+ }
+
// TODO(uabdullah): Consider/Implement TYPE (e.g Spam, TYPE_VOICEMAIL)
private void setPhoto(VoicemailEntry voicemailEntry) {
ContactPhotoManager.getInstance(context)
@@ -214,6 +232,10 @@ final class NewVoicemailViewHolder extends RecyclerView.ViewHolder implements On
isViewHolderExpanded = false;
viewHolderVoicemailUri = null;
+ primaryTextView.setTypeface(null, Typeface.NORMAL);
+ secondaryTextView.setTypeface(null, Typeface.NORMAL);
+ transcriptionTextView.setTypeface(null, Typeface.NORMAL);
+
mediaPlayerView.reset();
LogUtil.i(
diff --git a/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java b/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java
index 6a55483a4..55d36b364 100644
--- a/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java
+++ b/java/com/android/dialer/voicemail/listui/VoicemailCursorLoader.java
@@ -43,7 +43,8 @@ final class VoicemailCursorLoader extends CursorLoader {
AnnotatedCallLog.GEOCODED_LOCATION,
AnnotatedCallLog.CALL_TYPE,
AnnotatedCallLog.TRANSCRIPTION,
- AnnotatedCallLog.VOICEMAIL_URI
+ AnnotatedCallLog.VOICEMAIL_URI,
+ AnnotatedCallLog.IS_READ
};
// Indexes for VOICEMAIL_COLUMNS
@@ -60,6 +61,7 @@ final class VoicemailCursorLoader extends CursorLoader {
private static final int CALL_TYPE = 10;
private static final int TRANSCRIPTION = 11;
private static final int VOICEMAIL_URI = 12;
+ private static final int IS_READ = 13;
// TODO(zachh): Optimize indexes
VoicemailCursorLoader(Context context) {
@@ -95,6 +97,7 @@ final class VoicemailCursorLoader extends CursorLoader {
.setVoicemailUri(cursor.getString(VOICEMAIL_URI))
.setGeocodedLocation(cursor.getString(GEOCODED_LOCATION))
.setCallType(cursor.getInt(CALL_TYPE))
+ .setIsRead(cursor.getInt(IS_READ))
.build();
}
diff --git a/java/com/android/dialer/voicemail/model/VoicemailEntry.java b/java/com/android/dialer/voicemail/model/VoicemailEntry.java
index df30dee9c..702f52d17 100644
--- a/java/com/android/dialer/voicemail/model/VoicemailEntry.java
+++ b/java/com/android/dialer/voicemail/model/VoicemailEntry.java
@@ -32,7 +32,8 @@ public abstract class VoicemailEntry {
.setNumber(DialerPhoneNumber.getDefaultInstance())
.setPhotoId(0)
.setDuration(0)
- .setCallType(0);
+ .setCallType(0)
+ .setIsRead(0);
}
public abstract int id();
@@ -69,6 +70,8 @@ public abstract class VoicemailEntry {
public abstract int callType();
+ public abstract int isRead();
+
/** Builder for {@link VoicemailEntry}. */
@AutoValue.Builder
public abstract static class Builder {
@@ -99,6 +102,8 @@ public abstract class VoicemailEntry {
public abstract Builder setCallType(int callType);
+ public abstract Builder setIsRead(int isRead);
+
public abstract VoicemailEntry build();
}
}
diff --git a/java/com/android/incallui/AndroidManifest.xml b/java/com/android/incallui/AndroidManifest.xml
index b9d481b31..a98cc91d2 100644
--- a/java/com/android/incallui/AndroidManifest.xml
+++ b/java/com/android/incallui/AndroidManifest.xml
@@ -47,10 +47,13 @@
android:name="android.telephony.hide_voicemail_settings_menu"
android:value="true"/>
+ <!-- Go variants need hardware acceleration for IMS video calls even though it is disabled at
+ the application level -->
<activity
android:directBootAware="true"
android:excludeFromRecents="true"
android:exported="false"
+ android:hardwareAccelerated="true"
android:label="@string/phoneAppLabel"
android:launchMode="singleInstance"
android:name="com.android.incallui.InCallActivity"
diff --git a/java/com/android/incallui/NewReturnToCallController.java b/java/com/android/incallui/NewReturnToCallController.java
index ad49d6828..ca60a52c1 100644
--- a/java/com/android/incallui/NewReturnToCallController.java
+++ b/java/com/android/incallui/NewReturnToCallController.java
@@ -101,7 +101,7 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au
if (showing) {
hide();
} else {
- if (TelecomUtil.isInManagedCall(context)) {
+ if (getCall() != null) {
show();
}
}
@@ -157,22 +157,15 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au
@Override
public void onDisconnect(DialerCall call) {
- if (call.wasParentCall()) {
- // It's disconnected after the last child call is disconnected, and we already did everything
- // for the last child.
- LogUtil.i(
- "ReturnToCallController.onDisconnect", "being called for a parent call and do nothing");
- return;
- }
- if (bubble != null
- && bubble.isVisible()
- && (!TelecomUtil.isInManagedCall(context)
- || CallList.getInstance().getActiveOrBackgroundCall() != null)) {
- bubble.showText(context.getText(R.string.incall_call_ended));
- }
- // For conference call, we should hideAndReset for the last disconnected child call while the
- // parent call is still there.
- if (!CallList.getInstance().hasNonParentActiveOrBackgroundCall()) {
+ LogUtil.enterBlock("ReturnToCallController.onDisconnect");
+ if (bubble != null && bubble.isVisible() && (getCall() == null)) {
+ // Show "Call ended" and hide bubble when there is no outgoing, active or background call
+ LogUtil.i("ReturnToCallController.onDisconnect", "show call ended and hide bubble");
+ // Don't show text if it's Duo upgrade
+ // It doesn't work for Duo fallback upgrade since we're not considered in call
+ if (!TelecomUtil.isInCall(context) || CallList.getInstance().getIncomingCall() != null) {
+ bubble.showText(context.getText(R.string.incall_call_ended));
+ }
hideAndReset();
} else {
startContactInfoSearch();
@@ -197,19 +190,21 @@ public class NewReturnToCallController implements InCallUiListener, Listener, Au
}
private void startContactInfoSearch() {
- DialerCall dialerCall = CallList.getInstance().getIncomingCall();
- if (dialerCall == null) {
- dialerCall = CallList.getInstance().getOutgoingCall();
- }
- if (dialerCall == null) {
- dialerCall = CallList.getInstance().getActiveOrBackgroundCall();
- }
+ DialerCall dialerCall = getCall();
if (dialerCall != null) {
contactInfoCache.findInfo(
dialerCall, false /* isIncoming */, new ReturnToCallContactInfoCacheCallback(this));
}
}
+ private DialerCall getCall() {
+ DialerCall dialerCall = CallList.getInstance().getOutgoingCall();
+ if (dialerCall == null) {
+ dialerCall = CallList.getInstance().getActiveOrBackgroundCall();
+ }
+ return dialerCall;
+ }
+
private void onPhotoAvatarReceived(@NonNull Drawable photo) {
if (bubble != null) {
bubble.updatePhotoAvatar(photo);
diff --git a/java/com/android/incallui/call/DialerCall.java b/java/com/android/incallui/call/DialerCall.java
index 812024904..94c79e904 100644
--- a/java/com/android/incallui/call/DialerCall.java
+++ b/java/com/android/incallui/call/DialerCall.java
@@ -20,6 +20,7 @@ import android.Manifest.permission;
import android.content.Context;
import android.hardware.camera2.CameraCharacteristics;
import android.net.Uri;
+import android.os.Build;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
@@ -43,6 +44,7 @@ import android.telecom.VideoProfile;
import android.text.TextUtils;
import com.android.contacts.common.compat.CallCompat;
import com.android.contacts.common.compat.telecom.TelecomManagerCompat;
+import com.android.dialer.assisteddialing.ConcreteCreator;
import com.android.dialer.assisteddialing.TransformationInfo;
import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.callintent.CallIntentParser;
@@ -1073,19 +1075,50 @@ public class DialerCall implements VideoTechListener, StateChangedListener, Capa
return mLogState.isIncoming;
}
+ /**
+ * Try and determine if the call used assisted dialing.
+ *
+ * <p>We will not be able to verify a call underwent assisted dialing until the Platform
+ * implmentation is complete in P+.
+ *
+ * @return a boolean indicating assisted dialing may have been performed
+ */
public boolean isAssistedDialed() {
if (getIntentExtras() != null) {
- return getIntentExtras().getBoolean(TelephonyManagerCompat.IS_ASSISTED_DIALED, false);
+ // O_MR1 and below uses the existence of USE_ASSISTED_DIALING to indicate assisted dialing
+ // was used. The Dialer client is responsible for performing assisted dialing before
+ // placing the outgoing call.
+ //
+ // The existence of the assisted dialing extras indicates that assisted dialing took place.
+ if (getIntentExtras().getBoolean(TelephonyManagerCompat.USE_ASSISTED_DIALING, false)
+ && getAssistedDialingExtras() != null
+ && Build.VERSION.SDK_INT <= ConcreteCreator.BUILD_CODE_CEILING) {
+ return true;
+ }
+ }
+
+ // Starting in P+ USE_ASSISTED_DIALING indicates that the client requested the platform
+ // perform assisted dialing. PROPERTY_ASSISTED_DIALING_USED indicates assisted dialing took
+ // place.
+ if (hasProperty(TelephonyManagerCompat.PROPERTY_ASSISTED_DIALING_USED)
+ && Build.VERSION.SDK_INT > ConcreteCreator.BUILD_CODE_CEILING) {
+ return true;
}
return false;
}
+ @Nullable
public TransformationInfo getAssistedDialingExtras() {
- if (isAssistedDialed()) {
- return TransformationInfo.newInstanceFromBundle(
- getIntentExtras().getBundle(TelephonyManagerCompat.ASSISTED_DIALING_EXTRAS));
+ if (getIntentExtras() == null) {
+ return null;
}
- return null;
+
+ if (getIntentExtras().getBundle(TelephonyManagerCompat.ASSISTED_DIALING_EXTRAS) == null) {
+ return null;
+ }
+
+ return TransformationInfo.newInstanceFromBundle(
+ getIntentExtras().getBundle(TelephonyManagerCompat.ASSISTED_DIALING_EXTRAS));
}
public LatencyReport getLatencyReport() {
diff --git a/java/com/android/incallui/contactgrid/TopRow.java b/java/com/android/incallui/contactgrid/TopRow.java
index f8a485519..556b11ba0 100644
--- a/java/com/android/incallui/contactgrid/TopRow.java
+++ b/java/com/android/incallui/contactgrid/TopRow.java
@@ -175,7 +175,7 @@ public class TopRow {
}
}
- if (state.isAssistedDialed) {
+ if (state.isAssistedDialed && state.assistedDialingExtras != null) {
LogUtil.i("TopRow.getLabelForDialing", "using assisted dialing label.");
String countryCode =
String.valueOf(state.assistedDialingExtras.transformedNumberCountryCallingCode());
diff --git a/java/com/android/incallui/spam/SpamCallListListener.java b/java/com/android/incallui/spam/SpamCallListListener.java
index fa3dd6e01..e7603f041 100644
--- a/java/com/android/incallui/spam/SpamCallListListener.java
+++ b/java/com/android/incallui/spam/SpamCallListListener.java
@@ -455,6 +455,6 @@ public class SpamCallListListener implements CallList.Listener {
}
static String getNotificationTagForCall(@NonNull DialerCall call) {
- return NOTIFICATION_TAG_PREFIX + call.getNumber();
+ return NOTIFICATION_TAG_PREFIX + call.getUniqueCallId();
}
}
diff --git a/java/com/android/newbubble/NewBubble.java b/java/com/android/newbubble/NewBubble.java
index 3378ad81a..469c15d71 100644
--- a/java/com/android/newbubble/NewBubble.java
+++ b/java/com/android/newbubble/NewBubble.java
@@ -39,6 +39,7 @@ import android.support.annotation.VisibleForTesting;
import android.support.v4.graphics.ColorUtils;
import android.support.v4.os.BuildCompat;
import android.support.v4.view.animation.LinearOutSlowInInterpolator;
+import android.text.TextUtils;
import android.transition.TransitionManager;
import android.transition.TransitionValues;
import android.view.ContextThemeWrapper;
@@ -70,6 +71,7 @@ import com.android.newbubble.NewBubbleInfo.Action;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
+import java.util.Locale;
/**
* Creates and manages a bubble window from information in a {@link NewBubbleInfo}. Before creating,
@@ -406,6 +408,8 @@ public class NewBubble {
hideAfterText = false;
+ boolean isRtl =
+ TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL;
if (windowParams == null) {
// Apps targeting O+ must use TYPE_APPLICATION_OVERLAY, which is not available prior to O.
@SuppressWarnings("deprecation")
@@ -423,7 +427,7 @@ public class NewBubble {
| LayoutParams.FLAG_NOT_FOCUSABLE
| LayoutParams.FLAG_LAYOUT_NO_LIMITS,
PixelFormat.TRANSLUCENT);
- windowParams.gravity = Gravity.TOP | Gravity.LEFT;
+ windowParams.gravity = Gravity.TOP | (isRtl ? Gravity.RIGHT : Gravity.LEFT);
windowParams.x = leftBoundary;
windowParams.y = currentInfo.getStartingYPosition();
windowParams.height = LayoutParams.WRAP_CONTENT;
@@ -441,6 +445,9 @@ public class NewBubble {
viewHolder.getPrimaryButton().setScaleY(0);
viewHolder.getPrimaryAvatar().setAlpha(0f);
viewHolder.getPrimaryIcon().setAlpha(0f);
+ if (isRtl) {
+ onLeftRightSwitch(true);
+ }
}
viewHolder.setChildClickable(true);
@@ -795,7 +802,13 @@ public class NewBubble {
}
private void configureButton(Action action, NewCheckableButton button) {
- button.setCompoundDrawablesWithIntrinsicBounds(action.getIconDrawable(), null, null, null);
+ boolean isRtl =
+ TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL;
+ if (isRtl) {
+ button.setCompoundDrawablesWithIntrinsicBounds(null, null, action.getIconDrawable(), null);
+ } else {
+ button.setCompoundDrawablesWithIntrinsicBounds(action.getIconDrawable(), null, null, null);
+ }
button.setChecked(action.isChecked());
button.setEnabled(action.isEnabled());
button.setText(action.getName());
diff --git a/java/com/android/newbubble/res/layout/new_bubble_base.xml b/java/com/android/newbubble/res/layout/new_bubble_base.xml
index f83b75395..f6ce26dd1 100644
--- a/java/com/android/newbubble/res/layout/new_bubble_base.xml
+++ b/java/com/android/newbubble/res/layout/new_bubble_base.xml
@@ -21,6 +21,7 @@
android:layout_height="wrap_content"
android:clipChildren="true"
android:clipToPadding="false"
+ android:layoutDirection="ltr"
tools:theme="@style/Theme.AppCompat">
<RelativeLayout
android:id="@+id/bubble_primary_container"