Loading src/java/com/android/internal/telephony/ProxyController.java +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading src/java/com/android/internal/telephony/ims/RcsMessageStoreController.java +14 −38 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading src/java/com/android/internal/telephony/ims/RcsMessageStoreUtil.java +5 −5 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); Loading @@ -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); Loading @@ -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); Loading @@ -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); Loading tests/telephonytests/src/com/android/internal/telephony/ims/FakeProviderWithAsserts.java +84 −44 Original line number Diff line number Diff line Loading @@ -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)); } } } tests/telephonytests/src/com/android/internal/telephony/ims/RcsMessageStoreControllerTest.java +40 −32 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -46,7 +52,6 @@ public class RcsMessageStoreControllerTest extends TelephonyTest { private RcsMessageStoreController mRcsMessageStoreController; private MockContentResolver mContentResolver; private FakeProviderWithAsserts mFakeRcsProvider; private FakeProviderWithAsserts mFakeMmsSmsProvider; @Mock RcsParticipant mMockParticipant; Loading @@ -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); } Loading @@ -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); Loading @@ -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); } Loading @@ -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"); Loading @@ -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) { Loading @@ -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"); Loading @@ -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")); Loading @@ -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); Loading Loading
src/java/com/android/internal/telephony/ProxyController.java +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading
src/java/com/android/internal/telephony/ims/RcsMessageStoreController.java +14 −38 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading
src/java/com/android/internal/telephony/ims/RcsMessageStoreUtil.java +5 −5 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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); Loading @@ -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); Loading @@ -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); Loading @@ -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); Loading
tests/telephonytests/src/com/android/internal/telephony/ims/FakeProviderWithAsserts.java +84 −44 Original line number Diff line number Diff line Loading @@ -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)); } } }
tests/telephonytests/src/com/android/internal/telephony/ims/RcsMessageStoreControllerTest.java +40 −32 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -46,7 +52,6 @@ public class RcsMessageStoreControllerTest extends TelephonyTest { private RcsMessageStoreController mRcsMessageStoreController; private MockContentResolver mContentResolver; private FakeProviderWithAsserts mFakeRcsProvider; private FakeProviderWithAsserts mFakeMmsSmsProvider; @Mock RcsParticipant mMockParticipant; Loading @@ -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); } Loading @@ -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); Loading @@ -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); } Loading @@ -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"); Loading @@ -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) { Loading @@ -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"); Loading @@ -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")); Loading @@ -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); Loading