Support carrier presence-based video calling icon.

- Update SmartDial database to track carrier presence.
- Add video call style elements to dialer stylesheet.
- Tore out hair in frustration tracing through code.
- Add listeners to allow dialing of video calls from search results.

Bug: 20257833
Change-Id: I476cccb8c2805ae6f9949366fc5c2ce2669b7734
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 8c27265..66a45f9 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -40,13 +40,13 @@
         <item name="section_header_background">@drawable/list_title_holo</item>
         <item name="list_section_header_height">32dip</item>
         <item name="list_item_padding_top">12dp</item>
-        <item name="list_item_padding_right">32dp</item>
+        <item name="list_item_padding_right">24dp</item>
         <item name="list_item_padding_bottom">12dp</item>
         <item name="list_item_padding_left">16dp</item>
         <item name="list_item_gap_between_image_and_text">
             @dimen/contact_browser_list_item_gap_between_image_and_text
         </item>
-        <item name="list_item_gap_between_label_and_data">5dip</item>
+        <item name="list_item_gap_between_label_and_data">8dip</item>
         <item name="list_item_presence_icon_margin">4dip</item>
         <item name="list_item_presence_icon_size">16dip</item>
         <item name="list_item_photo_size">@dimen/contact_browser_list_item_photo_size</item>
@@ -85,6 +85,10 @@
         <item name="android:colorControlActivated">@color/dialer_theme_color</item>
         <item name="android:colorButtonNormal">@color/dialer_theme_color</item>
         <item name="android:textAppearanceButton">@style/DialerButtonTextStyle</item>
+
+        <!-- Video call icon -->
+        <item name="list_item_video_call_icon_size">32dip</item>
+        <item name="list_item_video_call_icon_margin">8dip</item>
     </style>
 
     <style name="DialerButtonTextStyle" parent="@android:style/TextAppearance.Material.Widget.Button">
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index a6fb98c..bcc45a0 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -1284,10 +1284,10 @@
     }
 
     @Override
-    public void onPickDataUri(Uri dataUri, int callInitiationType) {
+    public void onPickDataUri(Uri dataUri, boolean isVideoCall, int callInitiationType) {
         mClearSearchOnPause = true;
         PhoneNumberInteraction.startInteractionForPhoneCall(
-                DialtactsActivity.this, dataUri, callInitiationType);
+                DialtactsActivity.this, dataUri, isVideoCall, callInitiationType);
     }
 
     @Override
diff --git a/src/com/android/dialer/database/DialerDatabaseHelper.java b/src/com/android/dialer/database/DialerDatabaseHelper.java
index cc8631d..1f926c1 100644
--- a/src/com/android/dialer/database/DialerDatabaseHelper.java
+++ b/src/com/android/dialer/database/DialerDatabaseHelper.java
@@ -75,7 +75,7 @@
      *   0-98   KitKat
      * </pre>
      */
-    public static final int DATABASE_VERSION = 7;
+    public static final int DATABASE_VERSION = 8;
     public static final String DATABASE_NAME = "dialer.db";
 
     /**
@@ -115,6 +115,7 @@
         static final String IS_SUPER_PRIMARY = "is_super_primary";
         static final String IN_VISIBLE_GROUP = "in_visible_group";
         static final String IS_PRIMARY = "is_primary";
+        static final String CARRIER_PRESENCE = "carrier_presence";
         static final String LAST_SMARTDIAL_UPDATE_TIME = "last_smartdial_update_time";
     }
 
@@ -151,6 +152,7 @@
             Data.IS_SUPER_PRIMARY,              // 11
             Contacts.IN_VISIBLE_GROUP,          // 12
             Data.IS_PRIMARY,                    // 13
+            Data.CARRIER_PRESENCE,              // 14
         };
 
         static final int PHONE_ID = 0;
@@ -167,6 +169,7 @@
         static final int PHONE_IS_SUPER_PRIMARY = 11;
         static final int PHONE_IN_VISIBLE_GROUP = 12;
         static final int PHONE_IS_PRIMARY = 13;
+        static final int PHONE_CARRIER_PRESENCE = 14;
 
         /** Selects only rows that have been updated after a certain time stamp.*/
         static final String SELECT_UPDATED_CLAUSE =
@@ -268,20 +271,23 @@
         public final String phoneNumber;
         public final String lookupKey;
         public final long photoId;
+        public final int carrierPresence;
 
         public ContactNumber(long id, long dataID, String displayName, String phoneNumber,
-                String lookupKey, long photoId) {
+                String lookupKey, long photoId, int carrierPresence) {
             this.dataId = dataID;
             this.id = id;
             this.displayName = displayName;
             this.phoneNumber = phoneNumber;
             this.lookupKey = lookupKey;
             this.photoId = photoId;
+            this.carrierPresence = carrierPresence;
         }
 
         @Override
         public int hashCode() {
-            return Objects.hashCode(id, dataId, displayName, phoneNumber, lookupKey, photoId);
+            return Objects.hashCode(id, dataId, displayName, phoneNumber, lookupKey, photoId,
+                    carrierPresence);
         }
 
         @Override
@@ -296,7 +302,8 @@
                         && Objects.equal(this.displayName, that.displayName)
                         && Objects.equal(this.phoneNumber, that.phoneNumber)
                         && Objects.equal(this.lookupKey, that.lookupKey)
-                        && Objects.equal(this.photoId, that.photoId);
+                        && Objects.equal(this.photoId, that.photoId)
+                        && Objects.equal(this.carrierPresence, that.carrierPresence);
             }
             return false;
         }
@@ -398,7 +405,8 @@
                 + SmartDialDbColumns.STARRED + " INTEGER, "
                 + SmartDialDbColumns.IS_SUPER_PRIMARY + " INTEGER, "
                 + SmartDialDbColumns.IN_VISIBLE_GROUP + " INTEGER, "
-                + SmartDialDbColumns.IS_PRIMARY + " INTEGER"
+                + SmartDialDbColumns.IS_PRIMARY + " INTEGER, "
+                + SmartDialDbColumns.CARRIER_PRESENCE + " INTEGER NOT NULL DEFAULT 0"
                 + ");");
 
         db.execSQL("CREATE TABLE " + Tables.PREFIX_TABLE + " ("
@@ -473,6 +481,11 @@
             oldVersion = 7;
         }
 
+        if (oldVersion < 8) {
+            upgradeToVersion8(db);
+            oldVersion = 8;
+        }
+
         if (oldVersion != DATABASE_VERSION) {
             throw new IllegalStateException(
                     "error upgrading the database to version " + DATABASE_VERSION);
@@ -481,6 +494,10 @@
         setProperty(db, DATABASE_VERSION_PROPERTY, String.valueOf(DATABASE_VERSION));
     }
 
+    public void upgradeToVersion8(SQLiteDatabase db) {
+        db.execSQL("ALTER TABLE smartdial_table ADD carrier_presence INTEGER NOT NULL DEFAULT 0");
+    }
+
     /**
      * Stores a key-value pair in the {@link Tables#PROPERTIES} table.
      */
@@ -705,8 +722,9 @@
                     SmartDialDbColumns.IS_SUPER_PRIMARY + ", " +
                     SmartDialDbColumns.IN_VISIBLE_GROUP+ ", " +
                     SmartDialDbColumns.IS_PRIMARY + ", " +
+                    SmartDialDbColumns.CARRIER_PRESENCE + ", " +
                     SmartDialDbColumns.LAST_SMARTDIAL_UPDATE_TIME + ") " +
-                    " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+                    " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
             final SQLiteStatement insert = db.compileStatement(sqlInsert);
 
             final String numberSqlInsert = "INSERT INTO " + Tables.PREFIX_TABLE + " (" +
@@ -753,7 +771,8 @@
                 insert.bindLong(10, updatedContactCursor.getInt(PhoneQuery.PHONE_IS_SUPER_PRIMARY));
                 insert.bindLong(11, updatedContactCursor.getInt(PhoneQuery.PHONE_IN_VISIBLE_GROUP));
                 insert.bindLong(12, updatedContactCursor.getInt(PhoneQuery.PHONE_IS_PRIMARY));
-                insert.bindLong(13, currentMillis);
+                insert.bindLong(13, updatedContactCursor.getInt(PhoneQuery.PHONE_CARRIER_PRESENCE));
+                insert.bindLong(14, currentMillis);
                 insert.executeInsert();
                 final String contactPhoneNumber =
                         updatedContactCursor.getString(PhoneQuery.PHONE_NUMBER);
@@ -1020,7 +1039,8 @@
                 SmartDialDbColumns.PHOTO_ID + ", " +
                 SmartDialDbColumns.NUMBER + ", " +
                 SmartDialDbColumns.CONTACT_ID + ", " +
-                SmartDialDbColumns.LOOKUP_KEY +
+                SmartDialDbColumns.LOOKUP_KEY + ", " +
+                SmartDialDbColumns.CARRIER_PRESENCE +
                 " FROM " + Tables.SMARTDIAL_TABLE + " WHERE " +
                 SmartDialDbColumns.CONTACT_ID + " IN " +
                     " (SELECT " + PrefixColumns.CONTACT_ID +
@@ -1044,6 +1064,7 @@
             final int columnNumber = 3;
             final int columnId = 4;
             final int columnLookupKey = 5;
+            final int columnCarrierPresence = 6;
             if (DEBUG) {
                 stopWatch.lap("Found column IDs");
             }
@@ -1061,6 +1082,7 @@
                 final long id = cursor.getLong(columnId);
                 final long photoId = cursor.getLong(columnPhotoId);
                 final String lookupKey = cursor.getString(columnLookupKey);
+                final int carrierPresence = cursor.getInt(columnCarrierPresence);
 
                 /** If a contact already exists and another phone number of the contact is being
                  * processed, skip the second instance.
@@ -1081,7 +1103,7 @@
                     /** If a contact has not been added, add it to the result and the hash set.*/
                     duplicates.add(contactMatch);
                     result.add(new ContactNumber(id, dataID, displayName, phoneNumber, lookupKey,
-                            photoId));
+                            photoId, carrierPresence));
                     counter++;
                     if (DEBUG) {
                         stopWatch.lap("Added one result: Name: " + displayName);
diff --git a/src/com/android/dialer/dialpad/SmartDialCursorLoader.java b/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
index f83f18c..93b649b 100644
--- a/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
+++ b/src/com/android/dialer/dialpad/SmartDialCursorLoader.java
@@ -102,6 +102,7 @@
             row[PhoneQuery.LOOKUP_KEY] = contact.lookupKey;
             row[PhoneQuery.PHOTO_ID] = contact.photoId;
             row[PhoneQuery.DISPLAY_NAME] = contact.displayName;
+            row[PhoneQuery.CARRIER_PRESENCE] = contact.carrierPresence;
             cursor.addRow(row);
         }
         return cursor;
diff --git a/src/com/android/dialer/interactions/PhoneNumberInteraction.java b/src/com/android/dialer/interactions/PhoneNumberInteraction.java
index 96742fd..2472845 100644
--- a/src/com/android/dialer/interactions/PhoneNumberInteraction.java
+++ b/src/com/android/dialer/interactions/PhoneNumberInteraction.java
@@ -196,10 +196,12 @@
         private ListAdapter mPhonesAdapter;
         private List<PhoneItem> mPhoneList;
         private int mCallInitiationType;
+        private boolean mIsVideoCall;
 
         public static void show(FragmentManager fragmentManager, ArrayList<PhoneItem> phoneList,
-                int interactionType, int callInitiationType) {
-            PhoneDisambiguationDialogFragment fragment = new PhoneDisambiguationDialogFragment();
+                int interactionType, boolean isVideoCall, int callInitiationType) {
+            PhoneDisambiguationDialogFragment fragment = new PhoneDisambiguationDialogFragment(
+                isVideoCall);
             Bundle bundle = new Bundle();
             bundle.putParcelableArrayList(ARG_PHONE_LIST, phoneList);
             bundle.putInt(ARG_INTERACTION_TYPE, interactionType);
@@ -208,6 +210,11 @@
             fragment.show(fragmentManager, TAG);
         }
 
+        public PhoneDisambiguationDialogFragment(boolean isVideoCall) {
+            super();
+            mIsVideoCall = isVideoCall;
+        }
+
         @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
             final Activity activity = getActivity();
@@ -242,7 +249,7 @@
                 }
 
                 PhoneNumberInteraction.performAction(activity, phoneItem.phoneNumber,
-                        mInteractionType, mCallInitiationType);
+                        mInteractionType, mIsVideoCall, mCallInitiationType);
             } else {
                 dialog.dismiss();
             }
@@ -288,6 +295,7 @@
     private long mContactId = UNKNOWN_CONTACT_ID;
 
     private CursorLoader mLoader;
+    private boolean mIsVideoCall;
 
     /**
      * Constructs a new {@link PhoneNumberInteraction}. The constructor takes in a {@link Context}
@@ -298,25 +306,28 @@
     @VisibleForTesting
     /* package */ PhoneNumberInteraction(Context context, int interactionType,
             DialogInterface.OnDismissListener dismissListener) {
-        this(context, interactionType, dismissListener, LogState.INITIATION_UNKNOWN);
+        this(context, interactionType, dismissListener, false /*isVideoCall*/,
+                LogState.INITIATION_UNKNOWN);
     }
 
     private PhoneNumberInteraction(Context context, int interactionType,
-            DialogInterface.OnDismissListener dismissListener, int callInitiationType) {
+            DialogInterface.OnDismissListener dismissListener, boolean isVideoCall, 
+            int callInitiationType) {
         mContext = context;
         mInteractionType = interactionType;
         mDismissListener = dismissListener;
         mCallInitiationType = callInitiationType;
+        mIsVideoCall = isVideoCall;
     }
 
     private void performAction(String phoneNumber) {
-        PhoneNumberInteraction.performAction(mContext, phoneNumber, mInteractionType,
+        PhoneNumberInteraction.performAction(mContext, phoneNumber, mInteractionType, mIsVideoCall,
                 mCallInitiationType);
     }
 
     private static void performAction(
             Context context, String phoneNumber, int interactionType,
-            int callInitiationType) {
+            boolean isVideoCall, int callInitiationType) {
         Intent intent;
         switch (interactionType) {
             case ContactDisplayUtils.INTERACTION_SMS:
@@ -326,6 +337,7 @@
             default:
                 intent = new CallIntentBuilder(phoneNumber)
                         .setCallInitiationType(callInitiationType)
+                        .setIsVideoCall(isVideoCall)
                         .build();
                 break;
         }
@@ -454,12 +466,13 @@
      * @param activity that is calling this interaction. This must be of type
      * {@link TransactionSafeActivity} because we need to check on the activity state after the
      * phone numbers have been queried for.
+     * @param isVideoCall {@code true} if the call is a video call, {@code false} otherwise.
      * @param callInitiationType Indicates the UI affordance that was used to initiate the call.
      */
     public static void startInteractionForPhoneCall(TransactionSafeActivity activity, Uri uri,
-            int callInitiationType) {
+            boolean isVideoCall, int callInitiationType) {
         (new PhoneNumberInteraction(activity, ContactDisplayUtils.INTERACTION_CALL, null,
-                callInitiationType)).startInteraction(uri, true);
+                isVideoCall, callInitiationType)).startInteraction(uri, true);
     }
 
     /**
@@ -493,7 +506,7 @@
         }
         try {
             PhoneDisambiguationDialogFragment.show(activity.getFragmentManager(),
-                    phoneList, mInteractionType, mCallInitiationType);
+                    phoneList, mInteractionType, mIsVideoCall, mCallInitiationType);
         } catch (IllegalStateException e) {
             // ignore to be safe. Shouldn't happen because we checked the
             // activity wasn't destroyed, but to be safe.
diff --git a/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java b/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java
index 488bb33..7164de2 100644
--- a/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java
+++ b/src/com/android/dialer/list/DialerPhoneNumberListAdapter.java
@@ -2,12 +2,15 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.database.Cursor;
 import android.telephony.PhoneNumberUtils;
 import android.text.BidiFormatter;
 import android.text.TextDirectionHeuristics;
+import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.contacts.common.CallUtil;
 import com.android.contacts.common.GeoUtil;
 import com.android.contacts.common.list.ContactListItemView;
 import com.android.contacts.common.list.PhoneNumberListAdapter;
@@ -41,11 +44,13 @@
     private final boolean[] mShortcutEnabled = new boolean[SHORTCUT_COUNT];
 
     private final BidiFormatter mBidiFormatter = BidiFormatter.getInstance();
+    private boolean mVideoCallingEnabled = false;
 
     public DialerPhoneNumberListAdapter(Context context) {
         super(context);
 
         mCountryIso = GeoUtil.getCurrentCountryIso(context);
+        mVideoCallingEnabled = CallUtil.isVideoEnabled(context);
     }
 
     @Override
@@ -95,7 +100,8 @@
                 assignShortcutToView((ContactListItemView) convertView, shortcutType);
                 return convertView;
             } else {
-                final ContactListItemView v = new ContactListItemView(getContext(), null);
+                final ContactListItemView v = new ContactListItemView(getContext(), null,
+                        mVideoCallingEnabled);
                 assignShortcutToView(v, shortcutType);
                 return v;
             }
@@ -104,6 +110,16 @@
         }
     }
 
+    @Override
+    protected ContactListItemView newView(
+            Context context, int partition, Cursor cursor, int position, ViewGroup parent) {
+        final ContactListItemView view = super.newView(context, partition, cursor, position,
+                parent);
+
+        view.setSupportVideoCallIcon(mVideoCallingEnabled);
+        return view;
+    }
+
     /**
      * @param position The position of the item
      * @return The enabled shortcut type matching the given position if the item is a
diff --git a/src/com/android/dialer/list/RegularSearchFragment.java b/src/com/android/dialer/list/RegularSearchFragment.java
index d067b65..df18af0 100644
--- a/src/com/android/dialer/list/RegularSearchFragment.java
+++ b/src/com/android/dialer/list/RegularSearchFragment.java
@@ -74,6 +74,7 @@
         RegularSearchListAdapter adapter = new RegularSearchListAdapter(getActivity());
         adapter.setDisplayPhotos(true);
         adapter.setUseCallableUri(usesCallableUri());
+        adapter.setListener(this);
         return adapter;
     }
 
diff --git a/src/com/android/dialer/list/SearchFragment.java b/src/com/android/dialer/list/SearchFragment.java
index 9b0f536..d65223a 100644
--- a/src/com/android/dialer/list/SearchFragment.java
+++ b/src/com/android/dialer/list/SearchFragment.java
@@ -232,6 +232,7 @@
         DialerPhoneNumberListAdapter adapter = new DialerPhoneNumberListAdapter(getActivity());
         adapter.setDisplayPhotos(true);
         adapter.setUseCallableUri(super.usesCallableUri());
+        adapter.setListener(this);
         return adapter;
     }
 
diff --git a/src/com/android/dialer/list/SmartDialSearchFragment.java b/src/com/android/dialer/list/SmartDialSearchFragment.java
index 4984d95..fcb61ff 100644
--- a/src/com/android/dialer/list/SmartDialSearchFragment.java
+++ b/src/com/android/dialer/list/SmartDialSearchFragment.java
@@ -57,6 +57,7 @@
         adapter.setQuickContactEnabled(true);
         // Set adapter's query string to restore previous instance state.
         adapter.setQueryString(getQueryString());
+        adapter.setListener(this);
         return adapter;
     }
 
diff --git a/src/com/android/dialer/list/SpeedDialFragment.java b/src/com/android/dialer/list/SpeedDialFragment.java
index fcfff21..7e10297 100644
--- a/src/com/android/dialer/list/SpeedDialFragment.java
+++ b/src/com/android/dialer/list/SpeedDialFragment.java
@@ -118,7 +118,7 @@
         public void onContactSelected(Uri contactUri, Rect targetRect) {
             if (mPhoneNumberPickerActionListener != null) {
                 mPhoneNumberPickerActionListener.onPickDataUri(contactUri,
-                        LogState.INITIATION_SPEED_DIAL);
+                        false /* isVideoCall */, LogState.INITIATION_SPEED_DIAL);
             }
         }
 
diff --git a/tests/src/com/android/dialer/database/DatabaseTestUtils.java b/tests/src/com/android/dialer/database/DatabaseTestUtils.java
index 671497d..03b4938 100644
--- a/tests/src/com/android/dialer/database/DatabaseTestUtils.java
+++ b/tests/src/com/android/dialer/database/DatabaseTestUtils.java
@@ -76,6 +76,6 @@
                 isPrimary});
         nameCursor.addRow(new Object[]{displayName, contactId});
 
-        return new ContactNumber(contactId, id, displayName, number, lookupKey, 0);
+        return new ContactNumber(contactId, id, displayName, number, lookupKey, 0, 0);
     }
 }