Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c306319b authored by Sahin Caliskan's avatar Sahin Caliskan Committed by android-build-merger
Browse files

Merge "Implementation for RcsMessageStore [opt]"

am: 11fa87aa

Change-Id: I9d6ebddd7cb0daf4c94fcb5066599aeee7aaf34d
parents 4b638382 11fa87aa
Loading
Loading
Loading
Loading
+194 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.internal.telephony.ims;

import static android.provider.Telephony.RcsColumns.RcsEventTypes.ICON_CHANGED_EVENT_TYPE;
import static android.provider.Telephony.RcsColumns.RcsEventTypes.NAME_CHANGED_EVENT_TYPE;
import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_ALIAS_CHANGED_EVENT_TYPE;
import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_JOINED_EVENT_TYPE;
import static android.provider.Telephony.RcsColumns.RcsEventTypes.PARTICIPANT_LEFT_EVENT_TYPE;
import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.RCS_GROUP_THREAD_URI;
import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_URI;
import static android.provider.Telephony.RcsColumns.RcsParticipantEventColumns.ALIAS_CHANGE_EVENT_URI_PART;
import static android.provider.Telephony.RcsColumns.RcsParticipantEventColumns.NEW_ALIAS_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.DESTINATION_PARTICIPANT_ID_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.EVENT_TYPE_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.ICON_CHANGED_URI_PART;
import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NAME_CHANGED_URI_PART;
import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_ICON_URI_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.NEW_NAME_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.PARTICIPANT_JOINED_URI_PART;
import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.PARTICIPANT_LEFT_URI_PART;
import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.SOURCE_PARTICIPANT_ID_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsThreadEventColumns.TIMESTAMP_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsUnifiedEventHelper.RCS_EVENT_QUERY_URI;
import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.Rlog;
import android.telephony.ims.RcsEvent;
import android.telephony.ims.RcsEventQueryResult;
import android.telephony.ims.RcsGroupThreadIconChangedEvent;
import android.telephony.ims.RcsGroupThreadNameChangedEvent;
import android.telephony.ims.RcsGroupThreadParticipantJoinedEvent;
import android.telephony.ims.RcsGroupThreadParticipantLeftEvent;
import android.telephony.ims.RcsParticipantAliasChangedEvent;
import android.telephony.ims.RcsQueryContinuationToken;

import java.util.ArrayList;
import java.util.List;

class RcsEventQueryHelper {
    private final ContentResolver mContentResolver;

    RcsEventQueryHelper(ContentResolver contentResolver) {
        mContentResolver = contentResolver;
    }

    Uri getParticipantEventInsertionUri(int participantId) {
        return RCS_PARTICIPANT_URI.buildUpon().appendPath(Integer.toString(participantId))
                .appendPath(ALIAS_CHANGE_EVENT_URI_PART).build();
    }

    RcsEventQueryResult performEventQuery(Bundle bundle) throws RemoteException {
        RcsQueryContinuationToken continuationToken = null;
        List<RcsEvent> eventList = new ArrayList<>();

        try (Cursor cursor = mContentResolver.query(RCS_EVENT_QUERY_URI, null, bundle, null)) {
            if (cursor == null) {
                throw new RemoteException("Event query failed, bundle: " + bundle);
            }

            while (cursor.moveToNext()) {
                int eventType = cursor.getInt(cursor.getColumnIndex(EVENT_TYPE_COLUMN));
                switch (eventType) {
                    case PARTICIPANT_ALIAS_CHANGED_EVENT_TYPE:
                        eventList.add(createNewParticipantAliasChangedEvent(cursor));
                        break;
                    case PARTICIPANT_JOINED_EVENT_TYPE:
                        eventList.add(createNewParticipantJoinedEvent(cursor));
                        break;
                    case PARTICIPANT_LEFT_EVENT_TYPE:
                        eventList.add(createNewParticipantLeftEvent(cursor));
                        break;
                    case NAME_CHANGED_EVENT_TYPE:
                        eventList.add(createNewGroupNameChangedEvent(cursor));
                        break;
                    case ICON_CHANGED_EVENT_TYPE:
                        eventList.add(createNewGroupIconChangedEvent(cursor));
                        break;
                    default:
                        Rlog.e(RcsMessageStoreController.TAG,
                                "RcsEventQueryHelper: invalid event type: " + eventType);
                }
            }

            Bundle cursorExtras = cursor.getExtras();
            if (cursorExtras != null) {
                continuationToken = cursorExtras.getParcelable(QUERY_CONTINUATION_TOKEN);
            }
        }

        return new RcsEventQueryResult(continuationToken, eventList);
    }

    int createGroupThreadEvent(int eventType, long timestamp, int threadId,
            int originationParticipantId, ContentValues eventSpecificValues)
            throws RemoteException {
        ContentValues values = new ContentValues(eventSpecificValues);
        values.put(EVENT_TYPE_COLUMN, eventType);
        values.put(TIMESTAMP_COLUMN, timestamp);
        values.put(SOURCE_PARTICIPANT_ID_COLUMN, originationParticipantId);

        Uri eventUri = RCS_GROUP_THREAD_URI.buildUpon().appendPath(
                Integer.toString(threadId)).appendPath(getPathForEventType(eventType)).build();
        Uri insertionUri = mContentResolver.insert(eventUri, values);

        int eventId = 0;
        if (insertionUri != null) {
            eventId = Integer.parseInt(insertionUri.getLastPathSegment());
        }

        if (eventId <= 0) {
            throw new RemoteException(
                "Could not create event with type: " + eventType + " on thread: " + threadId);
        }
        return eventId;
    }

    private String getPathForEventType(int eventType) throws RemoteException {
        switch (eventType) {
            case PARTICIPANT_JOINED_EVENT_TYPE:
                return PARTICIPANT_JOINED_URI_PART;
            case PARTICIPANT_LEFT_EVENT_TYPE:
                return PARTICIPANT_LEFT_URI_PART;
            case NAME_CHANGED_EVENT_TYPE:
                return NAME_CHANGED_URI_PART;
            case ICON_CHANGED_EVENT_TYPE:
                return ICON_CHANGED_URI_PART;
            default:
                throw new RemoteException("Event type unrecognized: " + eventType);
        }
    }

    private RcsGroupThreadIconChangedEvent createNewGroupIconChangedEvent(Cursor cursor) {
        String newIcon = cursor.getString(cursor.getColumnIndex(NEW_ICON_URI_COLUMN));

        return new RcsGroupThreadIconChangedEvent(
                cursor.getLong(cursor.getColumnIndex(TIMESTAMP_COLUMN)),
                cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN)),
                cursor.getInt(cursor.getColumnIndex(SOURCE_PARTICIPANT_ID_COLUMN)),
                newIcon == null ? null : Uri.parse(newIcon));
    }

    private RcsGroupThreadNameChangedEvent createNewGroupNameChangedEvent(Cursor cursor) {
        return new RcsGroupThreadNameChangedEvent(
                cursor.getLong(cursor.getColumnIndex(TIMESTAMP_COLUMN)),
                cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN)),
                cursor.getInt(cursor.getColumnIndex(SOURCE_PARTICIPANT_ID_COLUMN)),
                cursor.getString(cursor.getColumnIndex(NEW_NAME_COLUMN)));
    }

    private RcsGroupThreadParticipantLeftEvent createNewParticipantLeftEvent(Cursor cursor) {
        return new RcsGroupThreadParticipantLeftEvent(
                cursor.getLong(cursor.getColumnIndex(TIMESTAMP_COLUMN)),
                cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN)),
                cursor.getInt(cursor.getColumnIndex(SOURCE_PARTICIPANT_ID_COLUMN)),
                cursor.getInt(cursor.getColumnIndex(DESTINATION_PARTICIPANT_ID_COLUMN)));
    }

    private RcsGroupThreadParticipantJoinedEvent createNewParticipantJoinedEvent(Cursor cursor) {
        return new RcsGroupThreadParticipantJoinedEvent(
                cursor.getLong(cursor.getColumnIndex(TIMESTAMP_COLUMN)),
                cursor.getInt(cursor.getColumnIndex(RCS_THREAD_ID_COLUMN)),
                cursor.getInt(cursor.getColumnIndex(SOURCE_PARTICIPANT_ID_COLUMN)),
                cursor.getInt(cursor.getColumnIndex(DESTINATION_PARTICIPANT_ID_COLUMN)));
    }

    private RcsParticipantAliasChangedEvent createNewParticipantAliasChangedEvent(Cursor cursor) {
        return new RcsParticipantAliasChangedEvent(
                cursor.getLong(cursor.getColumnIndex(TIMESTAMP_COLUMN)),
                cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN)),
                cursor.getString(cursor.getColumnIndex(NEW_ALIAS_COLUMN)));
    }
}
+213 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.internal.telephony.ims;

import static android.provider.Telephony.RcsColumns.CONTENT_AND_AUTHORITY;
import static android.provider.Telephony.RcsColumns.Rcs1To1ThreadColumns.RCS_1_TO_1_THREAD_URI_PART;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.CONTENT_TYPE_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.CONTENT_URI_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.DURATION_MILLIS_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.FILE_SIZE_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.FILE_TRANSFER_URI;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.FILE_TRANSFER_URI_PART;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.HEIGHT_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.PREVIEW_TYPE_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.PREVIEW_URI_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.SESSION_ID_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.SUCCESSFULLY_TRANSFERRED_BYTES;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.TRANSFER_STATUS_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsFileTransferColumns.WIDTH_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsGroupThreadColumns.RCS_GROUP_THREAD_URI_PART;
import static android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns.INCOMING_MESSAGE_URI;
import static android.provider.Telephony.RcsColumns.RcsIncomingMessageColumns.INCOMING_MESSAGE_URI_PART;
import static android.provider.Telephony.RcsColumns.RcsMessageColumns.GLOBAL_ID_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsMessageColumns.MESSAGE_ID_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsMessageColumns.ORIGINATION_TIMESTAMP_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsMessageColumns.STATUS_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsMessageColumns.SUB_ID_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsMessageDeliveryColumns.DELIVERY_URI_PART;
import static android.provider.Telephony.RcsColumns.RcsOutgoingMessageColumns.OUTGOING_MESSAGE_URI;
import static android.provider.Telephony.RcsColumns.RcsOutgoingMessageColumns.OUTGOING_MESSAGE_URI_PART;
import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsThreadColumns.RCS_THREAD_ID_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.MESSAGE_TYPE_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.MESSAGE_TYPE_INCOMING;
import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.MESSAGE_TYPE_OUTGOING;
import static android.provider.Telephony.RcsColumns.RcsUnifiedMessageColumns.UNIFIED_MESSAGE_URI;
import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.ims.RcsFileTransferCreationParameters;
import android.telephony.ims.RcsMessageCreationParameters;
import android.telephony.ims.RcsMessageQueryResult;
import android.telephony.ims.RcsQueryContinuationToken;

import com.android.ims.RcsTypeIdPair;

import java.util.ArrayList;
import java.util.List;

/**
 * A helper class focused on querying RCS messages from the
 * {@link com.android.providers.telephony.RcsProvider}
 */
class RcsMessageQueryHelper {

    private final ContentResolver mContentResolver;

    RcsMessageQueryHelper(ContentResolver contentResolver) {
        mContentResolver = contentResolver;
    }

    RcsMessageQueryResult performMessageQuery(Bundle bundle) throws RemoteException {
        RcsQueryContinuationToken continuationToken = null;
        List<RcsTypeIdPair> messageTypeIdPairs = new ArrayList<>();

        try (Cursor cursor = mContentResolver.query(UNIFIED_MESSAGE_URI, null, bundle, null)) {
            if (cursor == null) {
                throw new RemoteException("Could not perform message query, bundle: " + bundle);
            }

            while (cursor != null && cursor.moveToNext()) {
                boolean isIncoming = cursor.getInt(cursor.getColumnIndex(MESSAGE_TYPE_COLUMN))
                        == MESSAGE_TYPE_INCOMING;
                int messageId = cursor.getInt(cursor.getColumnIndex(MESSAGE_ID_COLUMN));

                messageTypeIdPairs.add(new RcsTypeIdPair(
                        isIncoming ? MESSAGE_TYPE_INCOMING : MESSAGE_TYPE_OUTGOING, messageId));
            }

            if (cursor != null) {
                Bundle cursorExtras = cursor.getExtras();
                if (cursorExtras != null) {
                    continuationToken =
                            cursorExtras.getParcelable(QUERY_CONTINUATION_TOKEN);
                }
            }
        }

        return new RcsMessageQueryResult(continuationToken, messageTypeIdPairs);
    }

    void createContentValuesForGenericMessage(ContentValues contentValues, int threadId,
            RcsMessageCreationParameters rcsMessageCreationParameters) {
        contentValues.put(GLOBAL_ID_COLUMN, rcsMessageCreationParameters.getRcsMessageGlobalId());
        contentValues.put(SUB_ID_COLUMN, rcsMessageCreationParameters.getSubId());
        contentValues.put(STATUS_COLUMN, rcsMessageCreationParameters.getMessageStatus());
        contentValues.put(ORIGINATION_TIMESTAMP_COLUMN,
                rcsMessageCreationParameters.getOriginationTimestamp());
        contentValues.put(RCS_THREAD_ID_COLUMN, threadId);
    }

    Uri getMessageInsertionUri(boolean isIncoming) {
        return isIncoming ? INCOMING_MESSAGE_URI : OUTGOING_MESSAGE_URI;
    }

    Uri getMessageDeletionUri(int messageId, boolean isIncoming, int rcsThreadId, boolean isGroup) {
        return CONTENT_AND_AUTHORITY.buildUpon().appendPath(
                isGroup ? RCS_GROUP_THREAD_URI_PART : RCS_1_TO_1_THREAD_URI_PART).appendPath(
                Integer.toString(rcsThreadId)).appendPath(
                isIncoming ? INCOMING_MESSAGE_URI_PART : OUTGOING_MESSAGE_URI_PART).appendPath(
                Integer.toString(messageId)).build();
    }

    Uri getMessageUpdateUri(int messageId, boolean isIncoming) {
        return getMessageInsertionUri(isIncoming).buildUpon().appendPath(
                Integer.toString(messageId)).build();
    }

    int[] getDeliveryParticipantsForMessage(int messageId) throws RemoteException {
        int[] participantIds;

        try (Cursor cursor = mContentResolver.query(getMessageDeliveryQueryUri(messageId), null,
                null, null)) {
            if (cursor == null) {
                throw new RemoteException(
                        "Could not query deliveries for message, messageId: " + messageId);
            }

            participantIds = new int[cursor.getCount()];

            for (int i = 0; cursor.moveToNext(); i++) {
                participantIds[i] = cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN));
            }
        }

        return participantIds;
    }

    Uri getMessageDeliveryUri(int messageId, int participantId) {
        return Uri.withAppendedPath(getMessageDeliveryQueryUri(messageId),
                Integer.toString(participantId));
    }

    long getLongValueFromDelivery(int messageId, int participantId,
            String columnName) throws RemoteException {
        try (Cursor cursor = mContentResolver.query(getMessageDeliveryUri(messageId, participantId),
                null, null, null)) {
            if (cursor == null || !cursor.moveToFirst()) {
                throw new RemoteException(
                        "Could not read delivery for message: " + messageId + ", participant: "
                                + participantId);
            }

            return cursor.getLong(cursor.getColumnIndex(columnName));
        }
    }

    private Uri getMessageDeliveryQueryUri(int messageId) {
        return getMessageInsertionUri(false).buildUpon().appendPath(
                Integer.toString(messageId)).appendPath(DELIVERY_URI_PART).build();
    }

    ContentValues getContentValuesForFileTransfer(
            RcsFileTransferCreationParameters fileTransferCreationParameters) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(SESSION_ID_COLUMN,
                fileTransferCreationParameters.getRcsFileTransferSessionId());
        contentValues.put(CONTENT_URI_COLUMN,
                fileTransferCreationParameters.getContentUri().toString());
        contentValues.put(CONTENT_TYPE_COLUMN, fileTransferCreationParameters.getContentMimeType());
        contentValues.put(FILE_SIZE_COLUMN, fileTransferCreationParameters.getFileSize());
        contentValues.put(SUCCESSFULLY_TRANSFERRED_BYTES,
                fileTransferCreationParameters.getTransferOffset());
        contentValues.put(TRANSFER_STATUS_COLUMN,
                fileTransferCreationParameters.getFileTransferStatus());
        contentValues.put(WIDTH_COLUMN, fileTransferCreationParameters.getWidth());
        contentValues.put(HEIGHT_COLUMN, fileTransferCreationParameters.getHeight());
        contentValues.put(DURATION_MILLIS_COLUMN,
                fileTransferCreationParameters.getMediaDuration());
        contentValues.put(PREVIEW_URI_COLUMN,
                fileTransferCreationParameters.getPreviewUri().toString());
        contentValues.put(PREVIEW_TYPE_COLUMN, fileTransferCreationParameters.getPreviewMimeType());

        return contentValues;
    }

    Uri getFileTransferInsertionUri(int messageId) {
        return UNIFIED_MESSAGE_URI.buildUpon().appendPath(Integer.toString(messageId)).appendPath(
                FILE_TRANSFER_URI_PART).build();
    }

    Uri getFileTransferUpdateUri(int partId) {
        return Uri.withAppendedPath(FILE_TRANSFER_URI, Integer.toString(partId));
    }
}
+815 −66

File changed.

Preview size limit exceeded, changes collapsed.

+161 −0

File added.

Preview size limit exceeded, changes collapsed.

+60 −6
Original line number Diff line number Diff line
@@ -15,15 +15,69 @@
 */
package com.android.internal.telephony.ims;

import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_ID_COLUMN;
import static android.provider.Telephony.RcsColumns.RcsParticipantColumns.RCS_PARTICIPANT_URI;
import static android.telephony.ims.RcsQueryContinuationToken.QUERY_CONTINUATION_TOKEN;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.ims.RcsParticipant;
import android.telephony.ims.RcsParticipantQueryResult;
import android.telephony.ims.RcsQueryContinuationToken;

import java.util.ArrayList;
import java.util.List;

class RcsParticipantQueryHelper {
    // Note: row Id needs to be appended to this URI to modify the canonical address
    static final String INDIVIDUAL_CANONICAL_ADDRESS_URI_AS_STRING =
            "content://mms-sms/canonical-address/";
    static final Uri CANONICAL_ADDRESSES_URI = Uri.parse("content://mms-sms/canonical-addresses");
    private final ContentResolver mContentResolver;

    RcsParticipantQueryHelper(ContentResolver contentResolver) {
        mContentResolver = contentResolver;
    }

    RcsParticipant getParticipantFromId(int participantId) throws RemoteException {
        RcsParticipant participant = null;
        try (Cursor cursor = mContentResolver.query(
                Uri.withAppendedPath(RCS_PARTICIPANT_URI, Integer.toString(participantId)),
                null, null, null)) {
            if (cursor == null && !cursor.moveToNext()) {
                throw new RemoteException("Could not find participant with id: " + participantId);
            }

            participant = new RcsParticipant(
                    cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN)));
        }
        return participant;
    }

    RcsParticipantQueryResult performParticipantQuery(Bundle bundle) throws RemoteException {
        RcsQueryContinuationToken continuationToken = null;
        List<Integer> participantList = new ArrayList<>();

    static final Uri PARTICIPANTS_URI = Uri.parse("content://rcs/participant");
    static final String RCS_ALIAS_COLUMN = "rcs_alias";
    static final String RCS_CANONICAL_ADDRESS_ID = "canonical_address_id";
        try (Cursor cursor = mContentResolver.query(RCS_PARTICIPANT_URI, null, bundle, null)) {
            if (cursor == null) {
                throw new RemoteException("Could not perform participant query, bundle: " + bundle);
            }

            while (cursor.moveToNext()) {
                participantList.add(
                        cursor.getInt(cursor.getColumnIndex(RCS_PARTICIPANT_ID_COLUMN)));
            }

            Bundle cursorExtras = cursor.getExtras();
            if (cursorExtras != null) {
                continuationToken = cursorExtras.getParcelable(QUERY_CONTINUATION_TOKEN);
            }
        }

        return new RcsParticipantQueryResult(continuationToken, participantList);
    }

    static Uri getUriForParticipant(int participantId) {
        return Uri.withAppendedPath(RCS_PARTICIPANT_URI, Integer.toString(participantId));
    }
}
Loading