Add SipAddress to Contacts UI in master

In gingerbread, change https://android-git.corp.google.com/g/62847 added
SIP addresses to the Contacts app.

This is that same change, manually applied to master.  (I didn't let it
auto-merge because that would have failed: the ViewContactActivity class
is totally gone in master.)

This change is identical to https://android-git.corp.google.com/g/62847
except that the change to ViewContactActivity.java is now applied to
ContactDetailFragment.java.  (The actual code change is identical,
though.)

Bug: 2942998
Change-Id: I18baf54966022d66d387d42d07fe2fdd5c1539f0
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2458d80..f7eaebb 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -199,6 +199,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/model/FallbackSource.java b/src/com/android/contacts/model/FallbackSource.java
index e052fed..9de87b7 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);
 
@@ -411,6 +416,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 149249a..6d4631f 100644
--- a/src/com/android/contacts/model/GoogleSource.java
+++ b/src/com/android/contacts/model/GoogleSource.java
@@ -50,6 +50,7 @@
         inflateNote(context, inflateLevel);
         inflateWebsite(context, inflateLevel);
         inflateEvent(context, inflateLevel);
+        inflateSipAddress(context, inflateLevel);
 
         // TODO: GOOGLE: GROUPMEMBERSHIP
 
@@ -58,16 +59,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);
 
@@ -112,36 +103,6 @@
     }
 
     @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);
-    }
-
-    @Override
     public int getHeaderColor(Context context) {
         return 0xff89c2c2;
     }
diff --git a/src/com/android/contacts/ui/QuickContactWindow.java b/src/com/android/contacts/ui/QuickContactWindow.java
index c90961e..f0c1a05 100644
--- a/src/com/android/contacts/ui/QuickContactWindow.java
+++ b/src/com/android/contacts/ui/QuickContactWindow.java
@@ -50,6 +50,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.provider.ContactsContract.Contacts;
@@ -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,
@@ -771,7 +773,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 4e80345..1d1e4e2 100644
--- a/src/com/android/contacts/util/Constants.java
+++ b/src/com/android/contacts/util/Constants.java
@@ -29,5 +29,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";
 
 }
diff --git a/src/com/android/contacts/views/detail/ContactDetailFragment.java b/src/com/android/contacts/views/detail/ContactDetailFragment.java
index 6ac36a8..af194db 100644
--- a/src/com/android/contacts/views/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/views/detail/ContactDetailFragment.java
@@ -65,6 +65,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.StructuredName;
 import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
 import android.provider.ContactsContract.CommonDataKinds.Website;
@@ -427,7 +428,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 {
@@ -438,6 +439,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);