private Contact loadContactEntity(ContentResolver resolver, Uri contactUri) {
    Uri entityUri = Uri.withAppendedPath(contactUri, Contacts.Entity.CONTENT_DIRECTORY);
    Cursor cursor =
        resolver.query(entityUri, ContactQuery.COLUMNS, null, null, Contacts.Entity.RAW_CONTACT_ID);
    if (cursor == null) {
      Log.e(TAG, "No cursor returned in loadContactEntity");
      return Contact.forNotFound(mRequestedUri);
    }

    try {
      if (!cursor.moveToFirst()) {
        cursor.close();
        return Contact.forNotFound(mRequestedUri);
      }

      /// M: fix ALPS00328937: Create the loaded contact starting with the header data.
      Contact contact = loadContactHeaderDataEX(cursor, contactUri);

      // Fill in the raw contacts, which is wrapped in an Entity and any
      // status data.  Initially, result has empty entities and statuses.
      long currentRawContactId = -1;
      RawContact rawContact = null;
      ImmutableList.Builder<RawContact> rawContactsBuilder =
          new ImmutableList.Builder<RawContact>();
      ImmutableMap.Builder<Long, DataStatus> statusesBuilder =
          new ImmutableMap.Builder<Long, DataStatus>();
      do {
        long rawContactId = cursor.getLong(ContactQuery.RAW_CONTACT_ID);
        if (rawContactId != currentRawContactId) {
          // First time to see this raw contact id, so create a new entity, and
          // add it to the result's entities.
          currentRawContactId = rawContactId;
          rawContact = new RawContact(loadRawContactValues(cursor));
          rawContactsBuilder.add(rawContact);
        }
        if (!cursor.isNull(ContactQuery.DATA_ID)) {
          ContentValues data = loadDataValues(cursor);
          rawContact.addDataItemValues(data);

          if (!cursor.isNull(ContactQuery.PRESENCE) || !cursor.isNull(ContactQuery.STATUS)) {
            final DataStatus status = new DataStatus(cursor);
            final long dataId = cursor.getLong(ContactQuery.DATA_ID);
            statusesBuilder.put(dataId, status);
          }
        }
      } while (cursor.moveToNext());

      contact.setRawContacts(rawContactsBuilder.build());
      contact.setStatuses(statusesBuilder.build());

      return contact;
    } finally {
      cursor.close();
    }
  }
  private Contact loadEncodedContactEntity(Uri uri) throws JSONException {
    final String jsonString = uri.getEncodedFragment();
    final JSONObject json = new JSONObject(jsonString);

    final long directoryId =
        Long.valueOf(uri.getQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY));

    final String displayName = json.optString(Contacts.DISPLAY_NAME);
    final String altDisplayName = json.optString(Contacts.DISPLAY_NAME_ALTERNATIVE, displayName);
    final int displayNameSource = json.getInt(Contacts.DISPLAY_NAME_SOURCE);
    final String photoUri = json.optString(Contacts.PHOTO_URI, null);
    final Contact contact =
        new Contact(
            uri,
            uri,
            mLookupUri,
            directoryId,
            null /* lookupKey */,
            -1 /* id */,
            -1 /* nameRawContactId */,
            displayNameSource,
            0 /* photoId */,
            photoUri,
            displayName,
            altDisplayName,
            null /* phoneticName */,
            false /* starred */,
            null /* presence */,
            false /* sendToVoicemail */,
            null /* customRingtone */,
            false /* isUserProfile */);

    contact.setStatuses(new ImmutableMap.Builder<Long, DataStatus>().build());

    final String accountName = json.optString(RawContacts.ACCOUNT_NAME, null);
    final String directoryName = uri.getQueryParameter(Directory.DISPLAY_NAME);
    if (accountName != null) {
      final String accountType = json.getString(RawContacts.ACCOUNT_TYPE);
      contact.setDirectoryMetaData(
          directoryName,
          null,
          accountName,
          accountType,
          json.optInt(Directory.EXPORT_SUPPORT, Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY));
    } else {
      contact.setDirectoryMetaData(
          directoryName,
          null,
          null,
          null,
          json.optInt(Directory.EXPORT_SUPPORT, Directory.EXPORT_SUPPORT_ANY_ACCOUNT));
    }

    final ContentValues values = new ContentValues();
    values.put(Data._ID, -1);
    values.put(Data.CONTACT_ID, -1);
    final RawContact rawContact = new RawContact(values);

    final JSONObject items = json.getJSONObject(Contacts.CONTENT_ITEM_TYPE);
    final Iterator keys = items.keys();
    while (keys.hasNext()) {
      final String mimetype = (String) keys.next();

      // Could be single object or array.
      final JSONObject obj = items.optJSONObject(mimetype);
      if (obj == null) {
        final JSONArray array = items.getJSONArray(mimetype);
        for (int i = 0; i < array.length(); i++) {
          final JSONObject item = array.getJSONObject(i);
          processOneRecord(rawContact, item, mimetype);
        }
      } else {
        processOneRecord(rawContact, obj, mimetype);
      }
    }

    contact.setRawContacts(new ImmutableList.Builder<RawContact>().add(rawContact).build());
    return contact;
  }