@Override
    protected Integer doInBackground(RawContactDeltaList... params) {
      final Context context = activityTarget;
      final ContentResolver resolver = context.getContentResolver();

      RawContactDeltaList state = params[0];

      if (state == null) {
        return RESULT_FAILURE;
      }

      // Trim any empty fields, and RawContacts, before persisting
      RawContactModifier.trimEmpty(state, mAccountTypeManager);

      // Attempt to persist changes
      int tries = 0;
      Integer result = RESULT_FAILURE;
      while (tries++ < PERSIST_TRIES) {
        try {
          // Build operations and try applying
          // Note: In case we've created a new raw_contact because the selected contact
          // is read-only, buildDiff() will create aggregation exceptions to join
          // the new one to the existing contact.
          final ArrayList<ContentProviderOperation> diff = state.buildDiff();
          ContentProviderResult[] results = null;
          if (!diff.isEmpty()) {
            results = resolver.applyBatch(ContactsContract.AUTHORITY, diff);
          }

          result = (diff.size() > 0) ? RESULT_SUCCESS : RESULT_UNCHANGED;
          break;

        } catch (RemoteException e) {
          // Something went wrong, bail without success
          Log.e(TAG, "Problem persisting user edits", e);
          break;

        } catch (OperationApplicationException e) {
          // Version consistency failed, bail without success
          Log.e(TAG, "Version consistency failed", e);
          break;
        }
      }

      return result;
    }
  @Override
  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    ListView list = (ListView) parent;
    int count = mAdapter.getCount();

    if (list.isItemChecked(count - 1)) {
      list.setItemChecked(count - 1, false);
      createNewGroup();
      return;
    }

    for (int i = 0; i < count; i++) {
      mAdapter.getItem(i).setChecked(list.isItemChecked(i));
    }

    // First remove the memberships that have been unchecked
    ArrayList<ValuesDelta> entries = mState.getMimeEntries(GroupMembership.CONTENT_ITEM_TYPE);
    if (entries != null) {
      for (ValuesDelta entry : entries) {
        if (!entry.isDelete()) {
          Long groupId = entry.getGroupRowId();
          if (groupId != null
              && groupId != mFavoritesGroupId
              && (groupId != mDefaultGroupId || mDefaultGroupVisible)
              && !isGroupChecked(groupId)) {
            entry.markDeleted();
          }
        }
      }
    }

    // Now add the newly selected items
    for (int i = 0; i < count; i++) {
      GroupSelectionItem item = mAdapter.getItem(i);
      long groupId = item.getGroupId();
      if (item.isChecked() && !hasMembership(groupId)) {
        ValuesDelta entry = RawContactModifier.insertChild(mState, mKind);
        entry.setGroupRowId(groupId);
      }
    }

    updateView();
  }
  private void setEntityDeltaList(RawContactDeltaList entityList) {
    if (entityList == null) {
      throw new IllegalStateException();
    }
    if (VERBOSE_LOGGING) {
      Log.v(TAG, "setEntityDeltaList: " + entityList);
    }

    mEntityDeltaList = entityList;

    // Find the editable raw_contact.
    mRawContactDelta = mEntityDeltaList.getFirstWritableRawContact(this);

    // If no editable raw_contacts are found, create one.
    if (mRawContactDelta == null) {
      mRawContactDelta = addEditableRawContact(this, mEntityDeltaList);

      if ((mRawContactDelta != null) && VERBOSE_LOGGING) {
        Log.v(TAG, "setEntityDeltaList: created editable raw_contact " + entityList);
      }
    }

    if (mRawContactDelta == null) {
      // Selected contact is read-only, and there's no editable account.
      mIsReadOnly = true;
      mEditableAccountType = null;
    } else {
      mIsReadOnly = false;

      mEditableAccountType = mRawContactDelta.getRawContactAccountType(this);

      // Handle any incoming values that should be inserted
      final Bundle extras = getIntent().getExtras();
      if (extras != null && extras.size() > 0) {
        // If there are any intent extras, add them as additional fields in the
        // RawContactDelta.
        RawContactModifier.parseExtras(this, mEditableAccountType, mRawContactDelta, extras);
      }
    }

    bindEditor();
  }
  /**
   * Create an {@link RawContactDelta} for a raw_contact on the first editable account found, and
   * add to the list. Also copy the structured name from an existing (read-only) raw_contact to the
   * new one, if any of the read-only contacts has a name.
   */
  private static RawContactDelta addEditableRawContact(
      Context context, RawContactDeltaList entityDeltaList) {
    // First, see if there's an editable account.
    final AccountTypeManager accounts = AccountTypeManager.getInstance(context);
    final List<AccountWithDataSet> editableAccounts = accounts.getAccounts(true);
    if (editableAccounts.size() == 0) {
      // No editable account type found.  The dialog will be read-only mode.
      return null;
    }
    final AccountWithDataSet editableAccount = editableAccounts.get(0);
    final AccountType accountType =
        accounts.getAccountType(editableAccount.type, editableAccount.dataSet);

    // Create a new RawContactDelta for the new raw_contact.
    final RawContact rawContact = new RawContact(context);
    rawContact.setAccount(editableAccount);

    final RawContactDelta entityDelta =
        new RawContactDelta(ValuesDelta.fromAfter(rawContact.getValues()));

    // Then, copy the structure name from an existing (read-only) raw_contact.
    for (RawContactDelta entity : entityDeltaList) {
      final ArrayList<ValuesDelta> readOnlyNames =
          entity.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
      if ((readOnlyNames != null) && (readOnlyNames.size() > 0)) {
        final ValuesDelta readOnlyName = readOnlyNames.get(0);
        final ValuesDelta newName =
            RawContactModifier.ensureKindExists(
                entityDelta, accountType, StructuredName.CONTENT_ITEM_TYPE);

        // Copy all the data fields.
        newName.copyStructuredNameFieldsFrom(readOnlyName);
        break;
      }
    }

    // Add the new RawContactDelta to the list.
    entityDeltaList.add(entityDelta);

    return entityDelta;
  }