Merge "Fix bugs when dropping down editor type list in Editor UI.(2/2)" into ub-contactsdialer-b-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 2d685d7..4f85f56 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -19,7 +19,7 @@
     android:versionCode="10400"
     android:versionName="1.4.0">
 
-    <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="23" />
+    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="23" />
     <original-package android:name="com.android.contacts" />
 
     <uses-permission android:name="android.permission.CALL_PHONE" />
diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java
index 54be5a0..0bc80e7 100755
--- a/src/com/android/contacts/ContactSaveService.java
+++ b/src/com/android/contacts/ContactSaveService.java
@@ -49,6 +49,7 @@
 import android.util.Log;
 import android.widget.Toast;
 
+import com.android.contacts.activities.ContactEditorBaseActivity;
 import com.android.contacts.common.compat.CompatUtils;
 import com.android.contacts.common.database.ContactUpdateUtils;
 import com.android.contacts.common.model.AccountTypeManager;
@@ -174,6 +175,45 @@
         sListeners.remove(listener);
     }
 
+    /**
+     * Returns true if the ContactSaveService was started successfully and false if an exception
+     * was thrown and a Toast error message was displayed.
+     */
+    public static boolean startService(Context context, Intent intent, int saveMode) {
+        try {
+            context.startService(intent);
+        } catch (Exception exception) {
+            final int resId;
+            switch (saveMode) {
+                case ContactEditorBaseActivity.ContactEditor.SaveMode.SPLIT:
+                    resId = R.string.contactUnlinkErrorToast;
+                    break;
+                case ContactEditorBaseActivity.ContactEditor.SaveMode.RELOAD:
+                    resId = R.string.contactJoinErrorToast;
+                    break;
+                case ContactEditorBaseActivity.ContactEditor.SaveMode.CLOSE:
+                    resId = R.string.contactSavedErrorToast;
+                    break;
+                default:
+                    resId = R.string.contactGenericErrorToast;
+            }
+            Toast.makeText(context, resId, Toast.LENGTH_SHORT).show();
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Utility method that starts service and handles exception.
+     */
+    public static void startService(Context context, Intent intent) {
+        try {
+            context.startService(intent);
+        } catch (Exception exception) {
+            Toast.makeText(context, R.string.contactGenericErrorToast, Toast.LENGTH_SHORT).show();
+        }
+    }
+
     @Override
     public Object getSystemService(String name) {
         Object service = super.getSystemService(name);
diff --git a/src/com/android/contacts/activities/AttachPhotoActivity.java b/src/com/android/contacts/activities/AttachPhotoActivity.java
index 9dad2e7..1abbecf 100644
--- a/src/com/android/contacts/activities/AttachPhotoActivity.java
+++ b/src/com/android/contacts/activities/AttachPhotoActivity.java
@@ -337,7 +337,7 @@
                 raw.getRawContactId() != null ? raw.getRawContactId() : -1,
                 mCroppedPhotoUri
         );
-        startService(intent);
+        ContactSaveService.startService(this, intent);
         finish();
     }
 
diff --git a/src/com/android/contacts/editor/CompactContactEditorFragment.java b/src/com/android/contacts/editor/CompactContactEditorFragment.java
index 3f401ee..ecc8f2b 100644
--- a/src/com/android/contacts/editor/CompactContactEditorFragment.java
+++ b/src/com/android/contacts/editor/CompactContactEditorFragment.java
@@ -165,28 +165,7 @@
                 ((Activity) mContext).getClass(),
                 CompactContactEditorActivity.ACTION_SAVE_COMPLETED, mUpdatedPhotos,
                 JOIN_CONTACT_ID_EXTRA_KEY, joinContactId);
-        try {
-            mContext.startService(intent);
-        } catch (Exception exception) {
-            final int resId;
-            switch (saveMode) {
-                case ContactEditorBaseActivity.ContactEditor.SaveMode.SPLIT:
-                    resId = R.string.contactUnlinkErrorToast;
-                    break;
-                case ContactEditorBaseActivity.ContactEditor.SaveMode.RELOAD:
-                    resId = R.string.contactJoinErrorToast;
-                    break;
-                case ContactEditorBaseActivity.ContactEditor.SaveMode.CLOSE:
-                    resId = R.string.contactSavedErrorToast;
-                    break;
-                default:
-                    resId = R.string.contactGenericErrorToast;
-            }
-            Toast.makeText(mContext, resId, Toast.LENGTH_SHORT).show();
-            onCancelEditConfirmed();
-            return false;
-        }
-        return true;
+        return startSaveService(mContext, intent, saveMode);
     }
 
     @Override
diff --git a/src/com/android/contacts/editor/CompactKindSectionView.java b/src/com/android/contacts/editor/CompactKindSectionView.java
index bab6fe3..7e5ff11 100644
--- a/src/com/android/contacts/editor/CompactKindSectionView.java
+++ b/src/com/android/contacts/editor/CompactKindSectionView.java
@@ -542,10 +542,11 @@
         }
         // Determine if we should add a new empty editor
         final DataKind dataKind = mKindSectionDataList.get(0).getDataKind();
+        final RawContactDelta rawContactDelta =
+                mKindSectionDataList.get(0).getRawContactDelta();
         if (dataKind == null // There is nothing we can do.
                 // We have already reached the maximum number of editors, don't add any more.
-                || (dataKind.typeOverallMax == mEditors.getChildCount()
-                        && dataKind.typeOverallMax != 0)
+                || !RawContactModifier.canInsert(rawContactDelta, dataKind)
                 // We have already reached the maximum number of empty editors, don't add any more.
                 || emptyEditors.size() == 1) {
             return;
@@ -556,8 +557,6 @@
             if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType) && mEditors.getChildCount() > 0) {
                 return;
             }
-            final RawContactDelta rawContactDelta =
-                    mKindSectionDataList.get(0).getRawContactDelta();
             final ValuesDelta values = RawContactModifier.insertChild(rawContactDelta, dataKind);
             final Editor.EditorListener editorListener = Event.CONTENT_ITEM_TYPE.equals(mimeType)
                     ? new EventEditorListener() : new NonNameEditorListener();
diff --git a/src/com/android/contacts/editor/ContactEditorBaseFragment.java b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
index 0d9b3a9..181bc44 100644
--- a/src/com/android/contacts/editor/ContactEditorBaseFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorBaseFragment.java
@@ -978,6 +978,15 @@
      */
     abstract protected boolean doSaveAction(int saveMode, Long joinContactId);
 
+    protected boolean startSaveService(Context context, Intent intent, int saveMode) {
+        final boolean result = ContactSaveService.startService(
+                context, intent, saveMode);
+        if (!result) {
+            onCancelEditConfirmed();
+        }
+        return result;
+    }
+
     //
     // State accessor methods
     //
diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java
index 38e43ae..146bc4c 100644
--- a/src/com/android/contacts/editor/ContactEditorFragment.java
+++ b/src/com/android/contacts/editor/ContactEditorFragment.java
@@ -426,8 +426,7 @@
                 SAVE_MODE_EXTRA_KEY, saveMode, isEditingUserProfile(),
                 ((Activity) mContext).getClass(), ContactEditorActivity.ACTION_SAVE_COMPLETED,
                 mUpdatedPhotos, JOIN_CONTACT_ID_EXTRA_KEY, joinContactId);
-        mContext.startService(intent);
-        return true;
+        return startSaveService(mContext, intent, saveMode);
     }
 
     @Override
diff --git a/src/com/android/contacts/editor/KindSectionView.java b/src/com/android/contacts/editor/KindSectionView.java
index ee11645..e612361 100644
--- a/src/com/android/contacts/editor/KindSectionView.java
+++ b/src/com/android/contacts/editor/KindSectionView.java
@@ -249,7 +249,7 @@
         } else if (isReadOnly()) {
             // We don't show empty editors for read only data kinds.
             return;
-        } else if (mKind.typeOverallMax == getEditorCount() && mKind.typeOverallMax != 0) {
+        } else if (!RawContactModifier.canInsert(mState, mKind)) {
             // We have already reached the maximum number of editors. Lets not add any more.
             return;
         } else if (emptyEditors.size() == 1) {
diff --git a/src/com/android/contacts/quickcontact/InvisibleContactUtil.java b/src/com/android/contacts/quickcontact/InvisibleContactUtil.java
index 706cfdb..fa1132b 100644
--- a/src/com/android/contacts/quickcontact/InvisibleContactUtil.java
+++ b/src/com/android/contacts/quickcontact/InvisibleContactUtil.java
@@ -96,7 +96,7 @@
                 contactDeltaList, "", 0, false, QuickContactActivity.class,
                 Intent.ACTION_VIEW, null, /* joinContactIdExtraKey =*/ null,
                 /* joinContactId =*/ null);
-        context.startService(intent);
+        ContactSaveService.startService(context, intent);
     }
 
     /** return default group id or -1 if no group or several groups are marked as default */