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

Commit 1fd54fcd authored by Sahin Caliskan's avatar Sahin Caliskan Committed by Gerrit Code Review
Browse files

Merge "Implement RcsParticipant (opt - 2)"

parents 7a580e32 1fd3105c
Loading
Loading
Loading
Loading
+75 −7
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 * 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.
@@ -20,7 +20,10 @@ import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.ServiceManager;
import android.provider.BaseColumns;
import android.provider.Telephony;
import android.telephony.Rlog;
import android.telephony.ims.Rcs1To1Thread;
import android.telephony.ims.RcsMessageStore;
@@ -114,7 +117,6 @@ public class RcsMessageStoreController extends IRcs.Stub {
    @Override
    public Rcs1To1Thread createRcs1To1Thread(RcsParticipant recipient) {
        // TODO - use recipient to add a thread

        ContentValues contentValues = new ContentValues(0);
        mContentResolver.insert(RcsThreadQueryHelper.THREADS_URI, contentValues);

@@ -123,12 +125,78 @@ public class RcsMessageStoreController extends IRcs.Stub {

    @Override
    public RcsParticipant createRcsParticipant(String canonicalAddress) {
        // TODO - refine implementation to disallow duplicate participants
        // 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(PARTICIPANT_ADDRESS_KEY, canonicalAddress);
        mContentResolver.insert(RcsThreadQueryHelper.PARTICIPANTS_URI, 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) {
                    Rlog.e(TAG, "Uri returned after canonical address insertion is malformed: "
                            + newCanonicalAddress, e);
                    return null;
                }
            }
        }

        // 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(RcsParticipantQueryHelper.RCS_CANONICAL_ADDRESS_ID,
                rowInCanonicalAddressesTable);

        // TODO - return the newly created participant
        Uri newParticipantUri = mContentResolver.insert(RcsParticipantQueryHelper.PARTICIPANTS_URI,
                contentValues);
        int newParticipantRowId;

        try {
            if (newParticipantUri != null) {
                newParticipantRowId = Integer.parseInt(newParticipantUri.getLastPathSegment());
            } else {
                Rlog.e(TAG, "Error inserting new participant into RcsProvider");
                return null;
            }
        } catch (NumberFormatException e) {
            Rlog.e(TAG,
                    "Uri returned after creating a participant is malformed: " + newParticipantUri);
            return null;
        }

        return new RcsParticipant(newParticipantRowId, canonicalAddress);
    }

    /**
     * TODO(sahinc) Instead of sending the update query directly to RcsProvider, this function
     * orchestrates between RcsProvider and MmsSmsProvider. This is because we are not fully decided
     * on whether we should have RCS storage in a separate database file.
     */
    @Override
    public void updateRcsParticipantCanonicalAddress(int id, String canonicalAddress) {
        // TODO - implement
    }

    @Override
    public void updateRcsParticipantAlias(int id, String alias) {
        ContentValues contentValues = new ContentValues(1);
        contentValues.put(RcsParticipantQueryHelper.RCS_ALIAS_COLUMN, alias);

        mContentResolver.update(RcsParticipantQueryHelper.PARTICIPANTS_URI, contentValues,
                BaseColumns._ID + "=?", new String[] {Integer.toString(id)});
    }
}
+29 −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 android.net.Uri;

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");

    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";
}
+99 −0
Original line number Diff line number Diff line
/*
 * Copyright 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 com.google.common.truth.Truth.assertThat;

import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.mock.MockContentProvider;

/**
 * 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;
    }

    void setExpectedInsertParameters(Uri uri, ContentValues contentValues) {
        mExpectedUri = uri;
        mExpectedContentValues = contentValues;
    }

    void setExpectedUpdateParameters(Uri uri, ContentValues contentValues, String whereClause,
            String[] whereArgs) {
        mExpectedUri = uri;
        mExpectedContentValues = contentValues;
        mExpectedWhereClause = whereClause;
        mExpectedWhereArgs = whereArgs;
    }

    void setInsertReturnValue(Uri returnValue) {
        mInsertReturnValue = returnValue;
    }

    void setQueryReturnValue(Cursor cursor) {

    }

    @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;
    }

    @Override
    public Uri insert(Uri uri, ContentValues contentValues) {
        assertThat(uri).isEqualTo(mExpectedUri);
        assertThat(contentValues).isEqualTo(mExpectedContentValues);
        return mInsertReturnValue;
    }

    @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;
    }
}
+45 −39
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 * Copyright 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.
@@ -21,11 +21,10 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.doReturn;

import android.database.Cursor;
import android.content.ContentValues;
import android.net.Uri;
import android.telephony.ims.RcsParticipant;
import android.telephony.ims.RcsThreadQueryParameters;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;

import com.android.internal.telephony.TelephonyTest;
@@ -40,7 +39,8 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {

    private RcsMessageStoreController mRcsMessageStoreController;
    private MockContentResolver mContentResolver;
    private FakeRcsProvider mFakeRcsProvider;
    private FakeProviderWithAsserts mFakeRcsProvider;
    private FakeProviderWithAsserts mFakeMmsSmsProvider;

    @Mock
    RcsParticipant mMockParticipant;
@@ -50,9 +50,11 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {
        super.setUp("RcsMessageStoreControllerTest");
        MockitoAnnotations.initMocks(this);

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

        mRcsMessageStoreController = new RcsMessageStoreController(mContentResolver, null);
    }
@@ -74,45 +76,49 @@ public class RcsMessageStoreControllerTest extends TelephonyTest {
        mRcsMessageStoreController.getRcsThreads(queryParameters);
    }

    /**
     * TODO(sahinc): fix the test once there is an implementation in place
     */
    @Test
    public void testGetMessageCount() {
        assertEquals(1018, mRcsMessageStoreController.getMessageCount(0));
    public void testCreateRcsParticipant() {
        // 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);

        // 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);

        RcsParticipant participant = mRcsMessageStoreController.createRcsParticipant("+5551234567");

        assertThat(participant.getId()).isEqualTo(1001);
        assertThat(participant.getCanonicalAddress()).isEqualTo("+5551234567");
    }

    /**
     * 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 FakeRcsProvider extends MockContentProvider {
        private Uri mExpectedUri;
        private String[] mExpectedProjection;
        private String mExpectedWhereClause;
        private String[] mExpectedWhereArgs;
        private String mExpectedSortOrder;

        void setExpectedQueryParameters(Uri uri, String[] projection, String whereClause,
                String[] whereArgs, String sortOrder) {
            mExpectedUri = uri;
            mExpectedProjection = projection;
            mExpectedWhereClause = whereClause;
            mExpectedWhereArgs = whereArgs;
            mExpectedSortOrder = sortOrder;
        }
    @Test
    public void testUpdateRcsParticipantAlias() {
        ContentValues contentValues = new ContentValues(1);
        contentValues.put("rcs_alias", "New Alias");
        mFakeRcsProvider.setExpectedUpdateParameters(Uri.parse("content://rcs/participant"),
                contentValues, "_id=?", new String[]{"551"});

        @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;
        mRcsMessageStoreController.updateRcsParticipantAlias(551, "New Alias");
    }

    /**
     * TODO(sahinc): fix the test once there is an implementation in place
     */
    @Test
    public void testGetMessageCount() {
        assertEquals(1018, mRcsMessageStoreController.getMessageCount(0));
    }
}