Add SipAddress to Contacts UI.  DO NOT MERGE.

Update the contacts app to display and edit the new SipAddress field.
(See https://android-git.corp.google.com/g/62672 for the corresponding
ContactsContract change.)

The details:

- Updated ViewContactActivity to display the SIP address if present,
  and to handle a click by firing off a CALL_PRIVILEGED intent with
  the address in a sip: URI.

  (Note: this code is wildly different in master, and the automerger
  is guaranteed to fail, so I'm marking this change DO NOT MERGE.
  I'll apply it manually in master as a separate change.)

- Updated FallbackSource and GoogleSource to know about SipAddress.

  A SIP address is displayed using a regular "phone call" icon for now,
  but we'll eventually want a SIP-specific variant.  (I'll separately
  ask the UI dudes for that.)  The SIP address field is edited using the
  "email address" style IME.

  Note I didn't touch the ExchangeSource class, which means that (for
  Exchange-synced contacts) we just won't allow editing this field.
  (Alternatively, we *could* allow the user to edit SIP addresses, and
  just have them silently not synced.  I'll check with the product
  guys about this.)

  Also cleaned up a bunch of unnecessary method overrides in
  GoogleSource.java.

- Updated QuickContactWindow to handle SIP addresses just like regular
  phone numbers, except that they fire off a sip: intent rather than a
  tel: intent.

  I still need to figure out how to make the "call SIP" icon different
  from the regular "call phone" icon though.

Bug: 2942998

Change-Id: I4f67641ef134be406606a99d9f9f07baeaadbf88
diff --git a/res/values/strings.xml b/res/values/strings.xml
index facf34c..e556dcd 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -193,6 +193,9 @@
     <!-- The label describing the Notes field of a contact. This field allows free form text entry about a contact -->
     <string name="label_notes">Notes</string>
 
+    <!-- The label describing the SIP address field of a contact. [CHAR LIMIT=20] -->
+    <string name="label_sip_address">SIP address</string>
+
     <!-- The label describing the custom ringtone for a contact -->
     <string name="label_ringtone">Ringtone</string>
 
diff --git a/src/com/android/contacts/ViewContactActivity.java b/src/com/android/contacts/ViewContactActivity.java
index a4a0892..80214ac 100644
--- a/src/com/android/contacts/ViewContactActivity.java
+++ b/src/com/android/contacts/ViewContactActivity.java
@@ -68,6 +68,7 @@
 import android.provider.ContactsContract.CommonDataKinds.Note;
 import android.provider.ContactsContract.CommonDataKinds.Organization;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.CommonDataKinds.Website;
 import android.telephony.PhoneNumberUtils;
@@ -1004,7 +1005,7 @@
                         entry.maxLines = 100;
                         mOtherEntries.add(entry);
                     } else if (Website.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
-                        // Build note entries
+                        // Build Website entries
                         entry.uri = null;
                         entry.maxLines = 10;
                         try {
@@ -1015,6 +1016,19 @@
                             Log.e(TAG, "Couldn't parse website: " + entry.data);
                         }
                         mOtherEntries.add(entry);
+                    } else if (SipAddress.CONTENT_ITEM_TYPE.equals(mimeType) && hasData) {
+                        // Build SipAddress entries
+                        entry.uri = null;
+                        entry.maxLines = 1;
+                        entry.intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
+                                Uri.fromParts(Constants.SCHEME_SIP, entry.data, null));
+                        mOtherEntries.add(entry);
+                        // TODO: Consider moving the SipAddress into its own
+                        // section (rather than lumping it in with mOtherEntries)
+                        // so that we can reposition it right under the phone number.
+                        // (Then, we'd also update FallbackSource.java to set
+                        // secondary=false for this field, and tweak the weight
+                        // of its DataKind.)
                     } else {
                         // Handle showing custom rows
                         entry.intent = new Intent(Intent.ACTION_VIEW, entry.uri);
diff --git a/src/com/android/contacts/model/FallbackSource.java b/src/com/android/contacts/model/FallbackSource.java
index 9cc855c..d77f8f5 100644
--- a/src/com/android/contacts/model/FallbackSource.java
+++ b/src/com/android/contacts/model/FallbackSource.java
@@ -32,6 +32,7 @@
 import android.provider.ContactsContract.CommonDataKinds.Organization;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.CommonDataKinds.Website;
@@ -56,6 +57,9 @@
     protected static final int FLAGS_POSTAL = EditorInfo.TYPE_CLASS_TEXT
             | EditorInfo.TYPE_TEXT_VARIATION_POSTAL_ADDRESS | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS
             | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
+    protected static final int FLAGS_SIP_ADDRESS = EditorInfo.TYPE_CLASS_TEXT
+            | EditorInfo.TYPE_TEXT_VARIATION_EMAIL_ADDRESS;  // since SIP addresses have the same
+                                                             // basic format as email addresses
 
     public FallbackSource() {
         this.accountType = null;
@@ -77,6 +81,7 @@
         inflateNote(context, inflateLevel);
         inflateWebsite(context, inflateLevel);
         inflateEvent(context, inflateLevel);
+        inflateSipAddress(context, inflateLevel);
 
         setInflatedLevel(inflateLevel);
 
@@ -435,6 +440,27 @@
         return kind;
     }
 
+    protected DataKind inflateSipAddress(Context context, int inflateLevel) {
+        DataKind kind = getKindForMimetype(SipAddress.CONTENT_ITEM_TYPE);
+        if (kind == null) {
+            // TODO: icon here should really be a SIP-specific variant of sym_action_call
+            kind = addKind(new DataKind(SipAddress.CONTENT_ITEM_TYPE,
+                    R.string.label_sip_address, android.R.drawable.sym_action_call, 130, true));
+            kind.isList = false;
+            kind.secondary = true;
+            kind.actionHeader = new SimpleInflater(R.string.label_sip_address);
+            kind.actionBody = new SimpleInflater(SipAddress.SIP_ADDRESS);
+        }
+
+        if (inflateLevel >= ContactsSource.LEVEL_CONSTRAINTS) {
+            kind.fieldList = Lists.newArrayList();
+            kind.fieldList.add(new EditField(SipAddress.SIP_ADDRESS,
+                                             R.string.label_sip_address, FLAGS_SIP_ADDRESS));
+        }
+
+        return kind;
+    }
+
     /**
      * Simple inflater that assumes a string resource has a "%s" that will be
      * filled from the given column.
diff --git a/src/com/android/contacts/model/GoogleSource.java b/src/com/android/contacts/model/GoogleSource.java
index 90abc92..d6dfbb6 100644
--- a/src/com/android/contacts/model/GoogleSource.java
+++ b/src/com/android/contacts/model/GoogleSource.java
@@ -66,6 +66,7 @@
         inflateNote(context, inflateLevel);
         inflateWebsite(context, inflateLevel);
         inflateEvent(context, inflateLevel);
+        inflateSipAddress(context, inflateLevel);
 
         // TODO: GOOGLE: GROUPMEMBERSHIP
 
@@ -74,16 +75,6 @@
     }
 
     @Override
-    protected DataKind inflateStructuredName(Context context, int inflateLevel) {
-        return super.inflateStructuredName(context, inflateLevel);
-    }
-
-    @Override
-    protected DataKind inflateNickname(Context context, int inflateLevel) {
-        return super.inflateNickname(context, inflateLevel);
-    }
-
-    @Override
     protected DataKind inflatePhone(Context context, int inflateLevel) {
         final DataKind kind = super.inflatePhone(context, ContactsSource.LEVEL_MIMETYPES);
 
@@ -127,36 +118,6 @@
         return kind;
     }
 
-    @Override
-    protected DataKind inflateStructuredPostal(Context context, int inflateLevel) {
-        return super.inflateStructuredPostal(context, inflateLevel);
-    }
-
-    @Override
-    protected DataKind inflateIm(Context context, int inflateLevel) {
-        return super.inflateIm(context, inflateLevel);
-    }
-
-    @Override
-    protected DataKind inflateOrganization(Context context, int inflateLevel) {
-        return super.inflateOrganization(context, inflateLevel);
-    }
-
-    @Override
-    protected DataKind inflatePhoto(Context context, int inflateLevel) {
-        return super.inflatePhoto(context, inflateLevel);
-    }
-
-    @Override
-    protected DataKind inflateNote(Context context, int inflateLevel) {
-        return super.inflateNote(context, inflateLevel);
-    }
-
-    @Override
-    protected DataKind inflateWebsite(Context context, int inflateLevel) {
-        return super.inflateWebsite(context, inflateLevel);
-    }
-
     // TODO: this should come from resource in the future
     // Note that frameworks/base/core/java/android/pim/vcard/VCardEntry.java also wants
     // this String.
diff --git a/src/com/android/contacts/ui/QuickContactWindow.java b/src/com/android/contacts/ui/QuickContactWindow.java
index 6fdcb01..1ed7e32 100644
--- a/src/com/android/contacts/ui/QuickContactWindow.java
+++ b/src/com/android/contacts/ui/QuickContactWindow.java
@@ -55,6 +55,7 @@
 import android.provider.ContactsContract.CommonDataKinds.Im;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.CommonDataKinds.Website;
 import android.text.TextUtils;
@@ -218,6 +219,7 @@
      */
     private static final String[] PRECEDING_MIMETYPES = new String[] {
             Phone.CONTENT_ITEM_TYPE,
+            SipAddress.CONTENT_ITEM_TYPE,
             Contacts.CONTENT_ITEM_TYPE,
             Constants.MIME_SMS_ADDRESS,
             Email.CONTENT_ITEM_TYPE,
@@ -772,7 +774,17 @@
                     final Uri callUri = Uri.fromParts(Constants.SCHEME_TEL, number, null);
                     mIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED, callUri);
                 }
-
+            } else if (SipAddress.CONTENT_ITEM_TYPE.equals(mimeType)) {
+                final String address = getAsString(cursor, SipAddress.SIP_ADDRESS);
+                if (!TextUtils.isEmpty(address)) {
+                    final Uri callUri = Uri.fromParts(Constants.SCHEME_SIP, address, null);
+                    mIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED, callUri);
+                    // TODO: This item currently appears with the same "phone"
+                    // icon as regular phone numbers, which is confusing if a
+                    // contact has both a regular number *and* a SIP address.
+                    // Need to figure out a way for this item to have a
+                    // special SIP-specific variant of that icon.
+                }
             } else if (Constants.MIME_SMS_ADDRESS.equals(mimeType)) {
                 final String number = getAsString(cursor, Phone.NUMBER);
                 if (!TextUtils.isEmpty(number)) {
diff --git a/src/com/android/contacts/util/Constants.java b/src/com/android/contacts/util/Constants.java
index e0178ad..a94608b 100644
--- a/src/com/android/contacts/util/Constants.java
+++ b/src/com/android/contacts/util/Constants.java
@@ -35,5 +35,6 @@
     public static final String SCHEME_SMSTO = "smsto";
     public static final String SCHEME_MAILTO = "mailto";
     public static final String SCHEME_IMTO = "imto";
+    public static final String SCHEME_SIP = "sip";
 
 }