Added support for displaying/redialing post-dial

Append dialed post-dial digits(if any exist) to the displayed number
and changes the intent sent by the redial button to include the
post-dial digits.

Bug: 24955678
Change-Id: I0ec2cb2d5504f7fd715132eba7d969ff284e23d1
diff --git a/src/com/android/dialer/CallDetailActivity.java b/src/com/android/dialer/CallDetailActivity.java
index 2e2bea8..690b3e1 100644
--- a/src/com/android/dialer/CallDetailActivity.java
+++ b/src/com/android/dialer/CallDetailActivity.java
@@ -107,11 +107,19 @@
             // All calls are from the same number and same contact, so pick the first detail.
             mDetails = details[0];
             mNumber = TextUtils.isEmpty(mDetails.number) ? null : mDetails.number.toString();
+            mPostDialDigits = TextUtils.isEmpty(mDetails.postDialDigits)
+                    ? "" : mDetails.postDialDigits;
             mDisplayNumber = mDetails.displayNumber;
 
             final CharSequence callLocationOrType = getNumberTypeOrLocation(mDetails);
 
-            final CharSequence displayNumber = mDetails.displayNumber;
+            final CharSequence displayNumber;
+            if (!TextUtils.isEmpty(mDetails.postDialDigits)) {
+                displayNumber = mDetails.number + mDetails.postDialDigits;
+            } else {
+                displayNumber = mDetails.displayNumber;
+            }
+
             final String displayNumberStr = mBidiFormatter.unicodeWrap(
                     displayNumber.toString(), TextDirectionHeuristics.LTR);
 
@@ -197,6 +205,7 @@
     private PhoneCallDetails mDetails;
     protected String mNumber;
     private Uri mVoicemailUri;
+    private String mPostDialDigits = "";
     private String mDisplayNumber;
 
     private ListView mHistoryList;
@@ -252,7 +261,7 @@
                     return;
                 }
                 mContext.startActivity(
-                        new CallIntentBuilder(mNumber)
+                        new CallIntentBuilder(getDialableNumber())
                                 .setCallInitiationType(LogState.INITIATION_CALL_DETAILS)
                                 .build());
             }
@@ -371,7 +380,8 @@
                 ClipboardUtils.copyText(mContext, null, mNumber, true);
                 break;
             case R.id.call_detail_action_edit_before_call:
-                Intent dialIntent = new Intent(Intent.ACTION_DIAL, CallUtil.getCallUri(mNumber));
+                Intent dialIntent = new Intent(Intent.ACTION_DIAL,
+                        CallUtil.getCallUri(getDialableNumber()));
                 DialerUtils.startActivityWithErrorToast(mContext, dialIntent);
                 break;
             default:
@@ -460,6 +470,10 @@
         sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
     }
 
+    private String getDialableNumber() {
+        return mNumber + mPostDialDigits;
+    }
+
     @NeededForTesting
     public boolean hasVoicemail() {
         return mVoicemailUri != null;
diff --git a/src/com/android/dialer/PhoneCallDetails.java b/src/com/android/dialer/PhoneCallDetails.java
index fb1827d..71aa26d 100644
--- a/src/com/android/dialer/PhoneCallDetails.java
+++ b/src/com/android/dialer/PhoneCallDetails.java
@@ -31,6 +31,8 @@
 public class PhoneCallDetails {
     // The number of the other party involved in the call.
     public CharSequence number;
+    // Post-dial digits associated with the outgoing call.
+    public String postDialDigits;
     // The number presenting rules set by the network, e.g., {@link Calls#PRESENTATION_ALLOWED}
     public int numberPresentation;
     // The formatted version of {@link #number}.
@@ -114,16 +116,19 @@
             CharSequence number,
             int numberPresentation,
             CharSequence formattedNumber,
+            CharSequence postDialDigits,
             boolean isVoicemail) {
         this.number = number;
         this.numberPresentation = numberPresentation;
         this.formattedNumber = formattedNumber;
         this.isVoicemail = isVoicemail;
+        this.postDialDigits = postDialDigits.toString();
         this.displayNumber = PhoneNumberDisplayUtil.getDisplayNumber(
                 context,
                 this.number,
                 this.numberPresentation,
                 this.formattedNumber,
+                this.postDialDigits,
                 this.isVoicemail).toString();
     }
 
diff --git a/src/com/android/dialer/calllog/CallLogAdapter.java b/src/com/android/dialer/calllog/CallLogAdapter.java
index 42b2f23..53fe9f7 100644
--- a/src/com/android/dialer/calllog/CallLogAdapter.java
+++ b/src/com/android/dialer/calllog/CallLogAdapter.java
@@ -423,6 +423,9 @@
         int count = getGroupSize(position);
 
         final String number = c.getString(CallLogQuery.NUMBER);
+        final String postDialDigits = PhoneNumberDisplayUtil.canShowPostDial()
+                ? c.getString(CallLogQuery.POST_DIAL_DIGITS) : "";
+
         final int numberPresentation = c.getInt(CallLogQuery.NUMBER_PRESENTATION);
         final PhoneAccountHandle accountHandle = PhoneAccountUtils.getAccount(
                 c.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME),
@@ -438,13 +441,15 @@
         ContactInfo info = ContactInfo.EMPTY;
         if (PhoneNumberUtil.canPlaceCallsTo(number, numberPresentation) && !isVoicemailNumber) {
             // Lookup contacts with this number
-            info = mContactInfoCache.getValue(number, countryIso, cachedContactInfo);
+            info = mContactInfoCache.getValue(number + postDialDigits,
+                    countryIso, cachedContactInfo);
         }
         CharSequence formattedNumber = info.formattedNumber == null
                 ? null : PhoneNumberUtils.createTtsSpannable(info.formattedNumber);
 
         final PhoneCallDetails details = new PhoneCallDetails(
-                mContext, number, numberPresentation, formattedNumber, isVoicemailNumber);
+                mContext, number, numberPresentation, formattedNumber,
+                postDialDigits, isVoicemailNumber);
         details.accountHandle = accountHandle;
         details.callTypes = getCallTypes(c, count);
         details.countryIso = countryIso;
@@ -478,6 +483,7 @@
         views.rowId = c.getLong(CallLogQuery.ID);
         // Store values used when the actions ViewStub is inflated on expansion.
         views.number = number;
+        views.postDialDigits = details.postDialDigits;
         views.displayNumber = details.displayNumber;
         views.numberPresentation = numberPresentation;
         views.callType = c.getInt(CallLogQuery.CALL_TYPE);
diff --git a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
index 7771563..bb7bdbd 100644
--- a/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
+++ b/src/com/android/dialer/calllog/CallLogAsyncTaskUtil.java
@@ -39,6 +39,9 @@
 
 import com.google.common.annotations.VisibleForTesting;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+
 public class CallLogAsyncTaskUtil {
     private static String TAG = CallLogAsyncTaskUtil.class.getSimpleName();
 
@@ -51,8 +54,9 @@
         GET_CALL_DETAILS,
     }
 
-    private static class CallDetailQuery {
-        static final String[] CALL_LOG_PROJECTION = new String[] {
+    private static final class CallDetailQuery {
+
+        private static final String[] CALL_LOG_PROJECTION_INTERNAL = new String[] {
             CallLog.Calls.DATE,
             CallLog.Calls.DURATION,
             CallLog.Calls.NUMBER,
@@ -66,6 +70,7 @@
             CallLog.Calls.DATA_USAGE,
             CallLog.Calls.TRANSCRIPTION
         };
+        public static final String[] CALL_LOG_PROJECTION;
 
         static final int DATE_COLUMN_INDEX = 0;
         static final int DURATION_COLUMN_INDEX = 1;
@@ -79,6 +84,17 @@
         static final int FEATURES = 9;
         static final int DATA_USAGE = 10;
         static final int TRANSCRIPTION_COLUMN_INDEX = 11;
+        static final int POST_DIAL_DIGITS = 12;
+
+        static {
+            ArrayList<String> projectionList = new ArrayList<>();
+            projectionList.addAll(Arrays.asList(CALL_LOG_PROJECTION_INTERNAL));
+            if (PhoneNumberDisplayUtil.canShowPostDial()) {
+                projectionList.add(AppCompatConstants.POST_DIAL_DIGITS);
+            }
+            projectionList.trimToSize();
+            CALL_LOG_PROJECTION = projectionList.toArray(new String[projectionList.size()]);
+        }
     }
 
     private static class CallLogDeleteBlockedCallQuery {
@@ -164,6 +180,8 @@
             // Read call log.
             final String countryIso = cursor.getString(CallDetailQuery.COUNTRY_ISO_COLUMN_INDEX);
             final String number = cursor.getString(CallDetailQuery.NUMBER_COLUMN_INDEX);
+            final String postDialDigits = PhoneNumberDisplayUtil.canShowPostDial()
+                    ? cursor.getString(CallDetailQuery.POST_DIAL_DIGITS) : "";
             final int numberPresentation =
                     cursor.getInt(CallDetailQuery.NUMBER_PRESENTATION_COLUMN_INDEX);
 
@@ -185,7 +203,8 @@
             }
 
             PhoneCallDetails details = new PhoneCallDetails(
-                    context, number, numberPresentation, info.formattedNumber, isVoicemail);
+                    context, number, numberPresentation, info.formattedNumber,
+                    postDialDigits, isVoicemail);
 
             details.accountHandle = accountHandle;
             details.contactUri = info.lookupUri;
diff --git a/src/com/android/dialer/calllog/CallLogGroupBuilder.java b/src/com/android/dialer/calllog/CallLogGroupBuilder.java
index 5eea096..194231b 100644
--- a/src/com/android/dialer/calllog/CallLogGroupBuilder.java
+++ b/src/com/android/dialer/calllog/CallLogGroupBuilder.java
@@ -17,7 +17,6 @@
 package com.android.dialer.calllog;
 
 import android.database.Cursor;
-import android.provider.CallLog.Calls;
 import android.telephony.PhoneNumberUtils;
 import android.text.format.Time;
 import android.text.TextUtils;
@@ -28,8 +27,6 @@
 
 import com.google.common.annotations.VisibleForTesting;
 
-import java.util.Objects;
-
 /**
  * Groups together calls in the call log.  The primary grouping attempts to group together calls
  * to and from the same number into a single row on the call log.
@@ -125,12 +122,15 @@
 
         // Instantiate the group values to those of the first call in the cursor.
         String groupNumber = cursor.getString(CallLogQuery.NUMBER);
+        String groupPostDialDigits = PhoneNumberDisplayUtil.canShowPostDial()
+                ? cursor.getString(CallLogQuery.POST_DIAL_DIGITS) : "";
         int groupCallType = cursor.getInt(CallLogQuery.CALL_TYPE);
         String groupAccountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME);
         String groupAccountId = cursor.getString(CallLogQuery.ACCOUNT_ID);
         int groupSize = 1;
 
         String number;
+        String numberPostDialDigits;
         int callType;
         String accountComponentName;
         String accountId;
@@ -138,17 +138,21 @@
         while (cursor.moveToNext()) {
             // Obtain the values for the current call to group.
             number = cursor.getString(CallLogQuery.NUMBER);
+            numberPostDialDigits = PhoneNumberDisplayUtil.canShowPostDial()
+                    ? cursor.getString(CallLogQuery.POST_DIAL_DIGITS) : "";
             callType = cursor.getInt(CallLogQuery.CALL_TYPE);
             accountComponentName = cursor.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME);
             accountId = cursor.getString(CallLogQuery.ACCOUNT_ID);
 
             final boolean isSameNumber = equalNumbers(groupNumber, number);
+            final boolean isSamePostDialDigits = groupPostDialDigits.equals(numberPostDialDigits);
             final boolean isSameAccount = isSameAccount(
                     groupAccountComponentName, accountComponentName, groupAccountId, accountId);
 
             // Group with the same number and account. Never group voicemails. Only group blocked
             // calls with other blocked calls.
-            if (isSameNumber && isSameAccount && areBothNotVoicemail(callType, groupCallType)
+            if (isSameNumber && isSameAccount && isSamePostDialDigits
+                    && areBothNotVoicemail(callType, groupCallType)
                     && (areBothNotBlocked(callType, groupCallType)
                             || areBothBlocked(callType, groupCallType))) {
                 // Increment the size of the group to include the current call, but do not create
@@ -168,6 +172,7 @@
 
                 // Update the group values to those of the current call.
                 groupNumber = number;
+                groupPostDialDigits = numberPostDialDigits;
                 groupCallType = callType;
                 groupAccountComponentName = accountComponentName;
                 groupAccountId = accountId;
diff --git a/src/com/android/dialer/calllog/CallLogListItemHelper.java b/src/com/android/dialer/calllog/CallLogListItemHelper.java
index be0e146..fb2bab8 100644
--- a/src/com/android/dialer/calllog/CallLogListItemHelper.java
+++ b/src/com/android/dialer/calllog/CallLogListItemHelper.java
@@ -16,7 +16,6 @@
 
 package com.android.dialer.calllog;
 
-import android.content.Context;
 import android.content.res.Resources;
 import android.provider.CallLog.Calls;
 import android.text.SpannableStringBuilder;
@@ -263,7 +262,7 @@
         if (!TextUtils.isEmpty(details.getPreferredName())) {
             recipient = details.getPreferredName();
         } else {
-            recipient = details.displayNumber;
+            recipient = details.displayNumber + details.postDialDigits;
         }
         return recipient;
     }
diff --git a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
index 89596f2..b82b35d 100644
--- a/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
+++ b/src/com/android/dialer/calllog/CallLogListItemViewHolder.java
@@ -111,6 +111,11 @@
     public String number;
 
     /**
+     * The post-dial numbers that are dialed following the phone number.
+     */
+    public String postDialDigits;
+
+    /**
      * The formatted phone number to display.
      */
     public String displayNumber;
@@ -416,7 +421,7 @@
                             IntentProvider.getReturnVoicemailCallIntentProvider());
                 } else {
                     primaryActionButtonView.setTag(
-                            IntentProvider.getReturnCallIntentProvider(number));
+                            IntentProvider.getReturnCallIntentProvider(number + postDialDigits));
                 }
 
                 primaryActionButtonView.setContentDescription(TextUtils.expandTemplate(
@@ -596,7 +601,7 @@
                     info.lookupUri,
                     (String) nameOrNumber /* top line of contact view in call subject dialog */,
                     isBusiness,
-                    number, /* callable number used for ACTION_CALL intent */
+                    number,
                     TextUtils.isEmpty(info.name) ? null : displayNumber, /* second line of contact
                                                                            view in dialog. */
                     numberType, /* phone number type (e.g. mobile) in second line of contact view */
diff --git a/src/com/android/dialer/calllog/CallLogQuery.java b/src/com/android/dialer/calllog/CallLogQuery.java
index 2b43c28..3f79801 100644
--- a/src/com/android/dialer/calllog/CallLogQuery.java
+++ b/src/com/android/dialer/calllog/CallLogQuery.java
@@ -18,11 +18,17 @@
 
 import android.provider.CallLog.Calls;
 
+import com.android.dialer.util.AppCompatConstants;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
 /**
  * The query for the call log table.
  */
 public final class CallLogQuery {
-    public static final String[] _PROJECTION = new String[] {
+
+    private static final String[] _PROJECTION_INTERNAL = new String[] {
             Calls._ID,                          // 0
             Calls.NUMBER,                       // 1
             Calls.DATE,                         // 2
@@ -73,4 +79,18 @@
     public static final int DATA_USAGE = 21;
     public static final int TRANSCRIPTION = 22;
     public static final int CACHED_PHOTO_URI = 23;
+    public static final int POST_DIAL_DIGITS = 24;
+
+    public static final String[] _PROJECTION;
+
+    static {
+        ArrayList<String> projectionList = new ArrayList<String>();
+        projectionList.addAll(Arrays.asList(_PROJECTION_INTERNAL));
+        if (PhoneNumberDisplayUtil.canShowPostDial()) {
+            projectionList.add(AppCompatConstants.POST_DIAL_DIGITS);
+        }
+        projectionList.trimToSize();
+        _PROJECTION = projectionList.toArray(new String[projectionList.size()]);
+    }
+
 }
diff --git a/src/com/android/dialer/calllog/ContactInfoHelper.java b/src/com/android/dialer/calllog/ContactInfoHelper.java
index e760750..5d88efe 100644
--- a/src/com/android/dialer/calllog/ContactInfoHelper.java
+++ b/src/com/android/dialer/calllog/ContactInfoHelper.java
@@ -397,7 +397,11 @@
         info.type = c.getInt(CallLogQuery.CACHED_NUMBER_TYPE);
         info.label = c.getString(CallLogQuery.CACHED_NUMBER_LABEL);
         String matchedNumber = c.getString(CallLogQuery.CACHED_MATCHED_NUMBER);
-        info.number = matchedNumber == null ? c.getString(CallLogQuery.NUMBER) : matchedNumber;
+        String postDialDigits = PhoneNumberDisplayUtil.canShowPostDial()
+                ? c.getString(CallLogQuery.POST_DIAL_DIGITS) : "";
+        info.number = (matchedNumber == null) ?
+                c.getString(CallLogQuery.NUMBER) + postDialDigits : matchedNumber;
+
         info.normalizedNumber = c.getString(CallLogQuery.CACHED_NORMALIZED_NUMBER);
         info.photoId = c.getLong(CallLogQuery.CACHED_PHOTO_ID);
         info.photoUri = UriUtils.nullForNonContactsUri(
diff --git a/src/com/android/dialer/calllog/PhoneNumberDisplayUtil.java b/src/com/android/dialer/calllog/PhoneNumberDisplayUtil.java
index 5030efd..91cd3e1 100644
--- a/src/com/android/dialer/calllog/PhoneNumberDisplayUtil.java
+++ b/src/com/android/dialer/calllog/PhoneNumberDisplayUtil.java
@@ -17,10 +17,9 @@
 package com.android.dialer.calllog;
 
 import android.content.Context;
-import android.content.res.Resources;
+import android.os.Build;
 import android.provider.CallLog.Calls;
 import android.text.TextUtils;
-import android.util.Log;
 
 import com.android.dialer.R;
 import com.android.dialer.util.PhoneNumberUtil;
@@ -67,6 +66,7 @@
             CharSequence number,
             int presentation,
             CharSequence formattedNumber,
+            CharSequence postDialDigits,
             boolean isVoicemail) {
         final CharSequence displayName = getDisplayName(context, number, presentation, isVoicemail);
         if (!TextUtils.isEmpty(displayName)) {
@@ -76,9 +76,18 @@
         if (!TextUtils.isEmpty(formattedNumber)) {
             return formattedNumber;
         } else if (!TextUtils.isEmpty(number)) {
-            return number;
+            return number.toString() + postDialDigits;
         } else {
             return "";
         }
     }
+
+    /**
+     * Returns whether we can expect the post-dial digits to be in the call log.
+     *
+     * These digits will be present in versions N+.
+     */
+    public static boolean canShowPostDial() {
+        return Build.VERSION.SDK_INT > Build.VERSION_CODES.M;
+    }
 }
diff --git a/src/com/android/dialer/util/AppCompatConstants.java b/src/com/android/dialer/util/AppCompatConstants.java
index 1d52eee..0bb78df 100644
--- a/src/com/android/dialer/util/AppCompatConstants.java
+++ b/src/com/android/dialer/util/AppCompatConstants.java
@@ -27,4 +27,6 @@
     public static final int CALLS_REJECTED_TYPE = 5;
     // Added to android.provider.CallLog.Calls in N+.
     public static final int CALLS_BLOCKED_TYPE = 6;
+    // Added to android.provider.CallLog.Calls in N+.
+    public static final String POST_DIAL_DIGITS = "post_dial_digits";
 }