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

Commit 3fbb1bd8 authored by Leland Miller's avatar Leland Miller Committed by Gerrit Code Review
Browse files

Merge changes from topic "rcs-cts"

* changes:
  Fix incorrect hardcoded column indices
  Initialize RcsMessageStoreController
  Remove dependency on canonical-addresses
parents bf0c8775 9541c938
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.telephony.Rlog;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.android.internal.telephony.ims.RcsMessageStoreController;
import com.android.internal.telephony.uicc.UiccController;

import java.util.ArrayList;
@@ -124,6 +125,8 @@ public class ProxyController {
        mCi = ci;
        mPhoneSwitcher = phoneSwitcher;

        RcsMessageStoreController.init(context);

        mUiccPhoneBookController = new UiccPhoneBookController(mPhones);
        mPhoneSubInfoController = new PhoneSubInfoController(mContext, mPhones);
        mUiccSmsController = new UiccSmsController(mContext);
+14 −38
Original line number Diff line number Diff line
@@ -87,7 +87,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.BaseColumns;
import android.provider.Telephony;
import android.telephony.Rlog;
import android.telephony.ims.RcsEventQueryParams;
@@ -302,51 +301,28 @@ public class RcsMessageStoreController extends IRcs.Stub {
     */
    @Override
    public int createRcsParticipant(String canonicalAddress, String alias) throws RemoteException {
        // Lookup the participant in RcsProvider to get the canonical row id in MmsSmsProvider
        int rowInCanonicalAddressesTable = Integer.MIN_VALUE;
        try (Cursor cursor = mContentResolver.query(
                RcsParticipantQueryHelper.CANONICAL_ADDRESSES_URI,
                new String[]{BaseColumns._ID}, Telephony.CanonicalAddressesColumns.ADDRESS + "=?",
                new String[]{canonicalAddress}, null)) {
            if (cursor != null && cursor.getCount() == 1 && cursor.moveToNext()) {
                rowInCanonicalAddressesTable = cursor.getInt(0);
            }
        }

        ContentValues contentValues = new ContentValues();
        contentValues.put(Telephony.CanonicalAddressesColumns.ADDRESS, canonicalAddress);

        if (rowInCanonicalAddressesTable == Integer.MIN_VALUE) {
            // We couldn't find any existing canonical addresses. Add a new one.
            Uri newCanonicalAddress = mContentResolver.insert(
                    RcsParticipantQueryHelper.CANONICAL_ADDRESSES_URI, contentValues);
            if (newCanonicalAddress != null) {
                try {
                    rowInCanonicalAddressesTable = Integer.parseInt(
                            newCanonicalAddress.getLastPathSegment());
                } catch (NumberFormatException e) {
                    throw new RemoteException(
                            "Uri returned after canonical address insertion is malformed: "
                                    + newCanonicalAddress);
                }
            }
        long canonicalAddressId = Telephony.RcsColumns.RcsCanonicalAddressHelper
                .getOrCreateCanonicalAddressId(mContentResolver, canonicalAddress);

        if (canonicalAddressId == TRANSACTION_FAILED) {
            throw new RemoteException("Could not create or make canonical address entry");
        }

        // Now we have a row in canonical_addresses table, and its value is in
        // rowInCanonicalAddressesTable. Put this row id in RCS participants table.
        contentValues.clear();
        contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, rowInCanonicalAddressesTable);
        contentValues.put(CANONICAL_ADDRESS_ID_COLUMN, canonicalAddressId);
        contentValues.put(RCS_ALIAS_COLUMN, alias);

        // TODO (123719857) - Disallow creation of duplicate participants
        Uri newParticipantUri = mContentResolver.insert(RCS_PARTICIPANT_URI, contentValues);
        int newParticipantRowId;

        try {
            if (newParticipantUri != null) {
                newParticipantRowId = Integer.parseInt(newParticipantUri.getLastPathSegment());
            } else {
                // TODO (123719857) - Disallow creation of duplicate participants
        if (newParticipantUri == null) {
            throw new RemoteException("Error inserting new participant into RcsProvider");
        }

        try {
            newParticipantRowId = Integer.parseInt(newParticipantUri.getLastPathSegment());
        } catch (NumberFormatException e) {
            throw new RemoteException(
                    "Uri returned after creating a participant is malformed: " + newParticipantUri);
+5 −5
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ public class RcsMessageStoreUtil {
            int idValue) throws RemoteException {
        try (Cursor cursor = getValueFromTableRow(tableUri, valueColumn, idColumn, idValue)) {
            if (cursor != null && cursor.moveToFirst()) {
                return cursor.getInt(0);
                return cursor.getInt(cursor.getColumnIndex(valueColumn));
            } else {
                throw new RemoteException("The row with (" + idColumn + " = " + idValue
                        + ") could not be found in " + tableUri);
@@ -53,7 +53,7 @@ public class RcsMessageStoreUtil {
            int idValue) throws RemoteException {
        try (Cursor cursor = getValueFromTableRow(tableUri, valueColumn, idColumn, idValue)) {
            if (cursor != null && cursor.moveToFirst()) {
                return cursor.getLong(0);
                return cursor.getLong(cursor.getColumnIndex(valueColumn));
            } else {
                throw new RemoteException("The row with (" + idColumn + " = " + idValue
                        + ") could not be found in " + tableUri);
@@ -65,7 +65,7 @@ public class RcsMessageStoreUtil {
            int idValue) throws RemoteException {
        try (Cursor cursor = getValueFromTableRow(tableUri, valueColumn, idColumn, idValue)) {
            if (cursor != null && cursor.moveToFirst()) {
                return cursor.getDouble(0);
                return cursor.getDouble(cursor.getColumnIndex(valueColumn));
            } else {
                throw new RemoteException("The row with (" + idColumn + " = " + idValue
                        + ") could not be found in " + tableUri);
@@ -77,7 +77,7 @@ public class RcsMessageStoreUtil {
            int idValue) throws RemoteException {
        try (Cursor cursor = getValueFromTableRow(tableUri, valueColumn, idColumn, idValue)) {
            if (cursor != null && cursor.moveToFirst()) {
                return cursor.getString(0);
                return cursor.getString(cursor.getColumnIndex(valueColumn));
            } else {
                throw new RemoteException("The row with (" + idColumn + " = " + idValue
                        + ") could not be found in " + tableUri);
@@ -89,7 +89,7 @@ public class RcsMessageStoreUtil {
            int idValue) throws RemoteException {
        try (Cursor cursor = getValueFromTableRow(tableUri, valueColumn, idColumn, idValue)) {
            if (cursor != null && cursor.moveToFirst()) {
                String uriAsString = cursor.getString(0);
                String uriAsString = cursor.getString(cursor.getColumnIndex(valueColumn));

                if (!TextUtils.isEmpty(uriAsString)) {
                    return Uri.parse(uriAsString);
+84 −44
Original line number Diff line number Diff line
@@ -23,77 +23,117 @@ import android.database.Cursor;
import android.net.Uri;
import android.test.mock.MockContentProvider;

import java.util.LinkedList;
import java.util.Queue;

/**
 * Mocking/spying ContentProviders break in different ways. Use a fake instead. The
 * RcsMessageStoreController doesn't care if RcsProvider works as expected (and doesn't have
 * visibility into it) - so verifying whether we use the correct parameters should suffice.
 */
class FakeProviderWithAsserts extends MockContentProvider {
    private Uri mExpectedUri;
    private String[] mExpectedProjection;
    private String mExpectedWhereClause;
    private String[] mExpectedWhereArgs;
    private String mExpectedSortOrder;
    private ContentValues mExpectedContentValues;

    private Cursor mQueryReturnValue;
    private Uri mInsertReturnValue;

    void setExpectedQueryParameters(Uri uri, String[] projection, String whereClause,
            String[] whereArgs, String sortOrder) {
        mExpectedUri = uri;
        mExpectedProjection = projection;
        mExpectedWhereClause = whereClause;
        mExpectedWhereArgs = whereArgs;
        mExpectedSortOrder = sortOrder;
    }
    /**
     * Interface implemented by all classes that describe expected operations.
     */
    private interface ExpectedOperation {}

    void setExpectedInsertParameters(Uri uri, ContentValues contentValues) {
        mExpectedUri = uri;
        mExpectedContentValues = contentValues;
    static class ExpectedQuery implements ExpectedOperation {
        private final Uri mUri;
        private final String[] mProjection;
        private final String mWhereClause;
        private final String[] mWhereArgs;
        private final String mSortOrder;
        private final Cursor mReturnValue;

        ExpectedQuery(Uri uri, String[] projection, String whereClause, String[] whereArgs,
                String sortOrder, Cursor returnValue) {
            mUri = uri;
            mProjection = projection;
            mWhereClause = whereClause;
            mWhereArgs = whereArgs;
            mSortOrder = sortOrder;
            mReturnValue = returnValue;
        }
    }

    void setExpectedUpdateParameters(Uri uri, ContentValues contentValues, String whereClause,
            String[] whereArgs) {
        mExpectedUri = uri;
        mExpectedContentValues = contentValues;
        mExpectedWhereClause = whereClause;
        mExpectedWhereArgs = whereArgs;
    static class ExpectedInsert implements ExpectedOperation {
        private Uri mUri;
        private ContentValues mContentValues;
        private Uri mReturnValue;

        ExpectedInsert(Uri uri, ContentValues contentValues, Uri returnValue) {
            mUri = uri;
            mContentValues = contentValues;
            mReturnValue = returnValue;
        }
    }

    static class ExpectedUpdate implements ExpectedOperation {
        private Uri mUri;
        private String mWhereClause;
        private String[] mWhereArgs;
        private ContentValues mContentValues;
        private int mReturnValue;

    void setInsertReturnValue(Uri returnValue) {
        mInsertReturnValue = returnValue;
        ExpectedUpdate(Uri uri, String whereClause, String[] whereArgs,
                ContentValues contentValues, int returnValue) {
            mUri = uri;
            mWhereClause = whereClause;
            mWhereArgs = whereArgs;
            mContentValues = contentValues;
            mReturnValue = returnValue;
        }
    }

    private Queue<ExpectedOperation> mExpectedOperations = new LinkedList<>();

    void setQueryReturnValue(Cursor cursor) {
    void addExpectedOperation(ExpectedOperation expectedOperation) {
        mExpectedOperations.add(expectedOperation);
    }

    private <T extends ExpectedOperation> T getExpectedOperation(Class<T> clazz) {
        ExpectedOperation expectedOperation = mExpectedOperations.remove();
        assertThat(expectedOperation).isNotNull();
        assertThat(expectedOperation).isInstanceOf(clazz);
        return clazz.cast(expectedOperation);
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String whereClause, String[] whereArgs,
            String sortOrder) {
        assertThat(uri).isEqualTo(mExpectedUri);
        assertThat(projection).isEqualTo(mExpectedProjection);
        assertThat(whereClause).isEqualTo(mExpectedWhereClause);
        assertThat(whereArgs).isEqualTo(mExpectedWhereArgs);
        assertThat(sortOrder).isEqualTo(mExpectedSortOrder);
        return null;
        ExpectedQuery expectedQuery = getExpectedOperation(ExpectedQuery.class);
        assertThat(uri).isEqualTo(expectedQuery.mUri);
        assertThat(projection).isEqualTo(expectedQuery.mProjection);
        assertThat(whereClause).isEqualTo(expectedQuery.mWhereClause);
        assertThat(whereArgs).isEqualTo(expectedQuery.mWhereArgs);
        assertThat(sortOrder).isEqualTo(expectedQuery.mSortOrder);
        return expectedQuery.mReturnValue;
    }

    @Override
    public Uri insert(Uri uri, ContentValues contentValues) {
        assertThat(uri).isEqualTo(mExpectedUri);
        assertThat(contentValues).isEqualTo(mExpectedContentValues);
        return mInsertReturnValue;
        ExpectedInsert expectedInsert = getExpectedOperation(ExpectedInsert.class);
        assertThat(uri).isEqualTo(expectedInsert.mUri);
        assertThatContentValuesAreEquivalent(contentValues, expectedInsert.mContentValues);
        return expectedInsert.mReturnValue;
    }

    @Override
    public int update(Uri uri, ContentValues contentValues, String whereClause,
            String[] whereArgs) {
        assertThat(uri).isEqualTo(mExpectedUri);
        assertThat(contentValues).isEqualTo(mExpectedContentValues);
        assertThat(whereClause).isEqualTo(mExpectedWhereClause);
        assertThat(whereArgs).isEqualTo(mExpectedWhereArgs);
        return 0;
        ExpectedUpdate expectedUpdate = getExpectedOperation(ExpectedUpdate.class);
        assertThat(uri).isEqualTo(expectedUpdate.mUri);
        assertThatContentValuesAreEquivalent(contentValues, expectedUpdate.mContentValues);
        assertThat(whereClause).isEqualTo(expectedUpdate.mWhereClause);
        assertThat(whereArgs).isEqualTo(expectedUpdate.mWhereArgs);
        return expectedUpdate.mReturnValue;
    }

    private void assertThatContentValuesAreEquivalent(
            ContentValues actual, ContentValues expected) {
        assertThat(actual.size()).isEqualTo(expected.size());
        for (String key : expected.keySet()) {
            assertThat(actual.get(key)).isEqualTo(expected.get(key));
        }
    }
}
+40 −32
Original line number Diff line number Diff line
@@ -27,13 +27,19 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;

import android.content.ContentValues;
import android.database.MatrixCursor;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.Telephony;
import android.provider.Telephony.RcsColumns.RcsParticipantColumns;
import android.telephony.ims.RcsParticipant;
import android.telephony.ims.RcsThreadQueryParams;
import android.test.mock.MockContentResolver;

import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.ims.FakeProviderWithAsserts.ExpectedInsert;
import com.android.internal.telephony.ims.FakeProviderWithAsserts.ExpectedQuery;
import com.android.internal.telephony.ims.FakeProviderWithAsserts.ExpectedUpdate;

import org.junit.After;
import org.junit.Before;
@@ -46,7 +52,6 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {
    private RcsMessageStoreController mRcsMessageStoreController;
    private MockContentResolver mContentResolver;
    private FakeProviderWithAsserts mFakeRcsProvider;
    private FakeProviderWithAsserts mFakeMmsSmsProvider;

    @Mock
    RcsParticipant mMockParticipant;
@@ -57,10 +62,8 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {
        MockitoAnnotations.initMocks(this);

        mFakeRcsProvider = new FakeProviderWithAsserts();
        mFakeMmsSmsProvider = new FakeProviderWithAsserts();
        mContentResolver = (MockContentResolver) mContext.getContentResolver();
        mContentResolver.addProvider("rcs", mFakeRcsProvider);
        mContentResolver.addProvider("mms-sms", mFakeMmsSmsProvider);

        mRcsMessageStoreController = new RcsMessageStoreController(mContentResolver, null);
    }
@@ -78,8 +81,8 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {
                        .setThreadType(THREAD_TYPE_GROUP).setResultLimit(30).build();

        // TODO - limit the query as per queryParameters. This will change how the query is executed
        mFakeRcsProvider.setExpectedQueryParameters(Uri.parse("content://rcs/thread"), null, null,
                null, null);
        mFakeRcsProvider.addExpectedOperation(new ExpectedQuery(
                Uri.parse("content://rcs/thread"), null, null, null, null, null));

        try {
            mRcsMessageStoreController.getRcsThreads(queryParameters);
@@ -90,27 +93,32 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {

    @Test
    public void testCreateRcsParticipant() throws RemoteException {
        // verify the first query to existing canonical addresses
        mFakeMmsSmsProvider.setExpectedQueryParameters(
                Uri.parse("content://mms-sms/canonical-addresses"), new String[]{"_id"},
                "address=?", new String[]{"+5551234567"}, null);

        // verify the insert on canonical addresses
        ContentValues expectedMmsSmsValues = new ContentValues(1);
        expectedMmsSmsValues.put("address", "+5551234567");
        mFakeMmsSmsProvider.setInsertReturnValue(
                Uri.parse("content://mms-sms/canonical-address/456"));
        mFakeMmsSmsProvider.setExpectedInsertParameters(
                Uri.parse("content://mms-sms/canonical-addresses"), expectedMmsSmsValues);
        String canonicalAddress = "+5551234567";

        // verify the first query to canonical addresses
        MatrixCursor canonicalAddressQueryCursor = new MatrixCursor(
                new String[]{Telephony.CanonicalAddressesColumns._ID});
        canonicalAddressQueryCursor.addRow(new Object[]{456});

        Uri expectedCanonicalAddressUri = Uri.parse("content://rcs/canonical-address")
                .buildUpon()
                .appendQueryParameter("address", canonicalAddress)
                .build();

        mFakeRcsProvider.addExpectedOperation(new ExpectedQuery(
                expectedCanonicalAddressUri, null, null, null, null, canonicalAddressQueryCursor));


        // verify the final insert on rcs participants
        ContentValues expectedRcsValues = new ContentValues(1);
        expectedRcsValues.put("canonical_address_id", 456);
        mFakeRcsProvider.setInsertReturnValue(Uri.parse("content://rcs/participant/1001"));
        mFakeRcsProvider.setExpectedInsertParameters(Uri.parse("content://rcs/participant"),
                expectedRcsValues);
        expectedRcsValues.put(RcsParticipantColumns.CANONICAL_ADDRESS_ID_COLUMN, 456);
        expectedRcsValues.put(RcsParticipantColumns.RCS_ALIAS_COLUMN, "alias");
        mFakeRcsProvider.addExpectedOperation(new ExpectedInsert(
                Uri.parse("content://rcs/participant"), expectedRcsValues,
                Uri.parse("content://rcs/participant/1001")));

        int participantId = mRcsMessageStoreController.createRcsParticipant("+5551234567", "alias");
        int participantId =
                mRcsMessageStoreController.createRcsParticipant(canonicalAddress, "alias");

        assertThat(participantId).isEqualTo(1001);
    }
@@ -119,8 +127,8 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {
    public void testUpdateRcsParticipantAlias() {
        ContentValues contentValues = new ContentValues(1);
        contentValues.put("rcs_alias", "New Alias");
        mFakeRcsProvider.setExpectedUpdateParameters(Uri.parse("content://rcs/participant/551"),
                contentValues, null, null);
        mFakeRcsProvider.addExpectedOperation(new ExpectedUpdate(
                Uri.parse("content://rcs/participant/551"), null, null, contentValues, 0));

        try {
            mRcsMessageStoreController.setRcsParticipantAlias(551, "New Alias");
@@ -133,8 +141,8 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {
    public void testSet1To1ThreadFallbackThreadId() {
        ContentValues contentValues = new ContentValues(1);
        contentValues.put(FALLBACK_THREAD_ID_COLUMN, 456L);
        mFakeRcsProvider.setExpectedUpdateParameters(Uri.parse("content://rcs/p2p_thread/123"),
                contentValues, null, null);
        mFakeRcsProvider.addExpectedOperation(new ExpectedUpdate(
                Uri.parse("content://rcs/p2p_thread/123"), null, null, contentValues, 0));
        try {
            mRcsMessageStoreController.set1To1ThreadFallbackThreadId(123, 456L);
        } catch (RemoteException e) {
@@ -146,8 +154,8 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {
    public void testSetGroupThreadName() {
        ContentValues contentValues = new ContentValues(1);
        contentValues.put(GROUP_NAME_COLUMN, "new name");
        mFakeRcsProvider.setExpectedUpdateParameters(Uri.parse("content://rcs/group_thread/345"),
                contentValues, null, null);
        mFakeRcsProvider.addExpectedOperation(new ExpectedUpdate(
                Uri.parse("content://rcs/group_thread/345"), null, null, contentValues, 0));

        try {
            mRcsMessageStoreController.setGroupThreadName(345, "new name");
@@ -160,8 +168,8 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {
    public void testSetGroupThreadIcon() {
        ContentValues contentValues = new ContentValues(1);
        contentValues.put(GROUP_ICON_COLUMN, "newIcon");
        mFakeRcsProvider.setExpectedUpdateParameters(Uri.parse("content://rcs/group_thread/345"),
                contentValues, null, null);
        mFakeRcsProvider.addExpectedOperation(new ExpectedUpdate(
                Uri.parse("content://rcs/group_thread/345"), null, null, contentValues, 0));

        try {
            mRcsMessageStoreController.setGroupThreadIcon(345, Uri.parse("newIcon"));
@@ -174,8 +182,8 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {
    public void testSetGroupThreadOwner() {
        ContentValues contentValues = new ContentValues(1);
        contentValues.put(OWNER_PARTICIPANT_COLUMN, 9);
        mFakeRcsProvider.setExpectedUpdateParameters(Uri.parse("content://rcs/group_thread/454"),
                contentValues, null, null);
        mFakeRcsProvider.addExpectedOperation(new ExpectedUpdate(
                Uri.parse("content://rcs/group_thread/454"), null, null, contentValues, 0));

        RcsParticipant participant = new RcsParticipant(9);