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

Commit bdd89374 authored by Calvin Pan's avatar Calvin Pan Committed by Brad Ebinger
Browse files

Fixing empty tuple capability always expired

EAB stores capabilities in two different tables (common, presence), and
stores the expiration time in the Presence table, because a contact may
have multiple tuples, and each tuple may have its own expiration time.

But if the server sends capabilities with empty tuples, EAB will not
store any data in the Presence table. It causes the EAB to treat it as
an expired capability and request a new capability every time.

[Fix] If there is no tuple ability, store the current timestamp and null
presence attributes in the presence table.

Bug: 203676348
Test: atest EabControllerTest
Merged-In: Id54a71b71d353f3d2fa5c3246ab534ad581fe245
Change-Id: Id54a71b71d353f3d2fa5c3246ab534ad581fe245
parent 35a6054b
Loading
Loading
Loading
Loading
+51 −24
Original line number Original line Diff line number Diff line
@@ -323,8 +323,10 @@ public class EabControllerImpl implements EabController {
        if (mechanism == CAPABILITY_MECHANISM_PRESENCE) {
        if (mechanism == CAPABILITY_MECHANISM_PRESENCE) {
            PresenceBuilder builder = new PresenceBuilder(
            PresenceBuilder builder = new PresenceBuilder(
                    contactUri, SOURCE_TYPE_CACHED, result);
                    contactUri, SOURCE_TYPE_CACHED, result);
            builder.addCapabilityTuple(createPresenceTuple(contactUri, cursor));
            RcsContactPresenceTuple tuple = createPresenceTuple(contactUri, cursor);

            if (tuple != null) {
                builder.addCapabilityTuple(tuple);
            }
            String entityUri = getStringValue(cursor, EabProvider.EabCommonColumns.ENTITY_URI);
            String entityUri = getStringValue(cursor, EabProvider.EabCommonColumns.ENTITY_URI);
            if (!TextUtils.isEmpty(entityUri)) {
            if (!TextUtils.isEmpty(entityUri)) {
                builder.setEntityUri(Uri.parse(entityUri));
                builder.setEntityUri(Uri.parse(entityUri));
@@ -390,6 +392,9 @@ public class EabControllerImpl implements EabController {
        serviceCapabilities = serviceCapabilitiesBuilder.build();
        serviceCapabilities = serviceCapabilitiesBuilder.build();


        // Create RcsContactPresenceTuple
        // Create RcsContactPresenceTuple
        boolean isTupleEmpty = TextUtils.isEmpty(status) && TextUtils.isEmpty(serviceId)
                && TextUtils.isEmpty(version);
        if (!isTupleEmpty) {
            RcsContactPresenceTuple.Builder rcsContactPresenceTupleBuilder =
            RcsContactPresenceTuple.Builder rcsContactPresenceTupleBuilder =
                    new RcsContactPresenceTuple.Builder(status, serviceId, version);
                    new RcsContactPresenceTuple.Builder(status, serviceId, version);
            if (description != null) {
            if (description != null) {
@@ -411,8 +416,10 @@ public class EabControllerImpl implements EabController {
                    Log.w(TAG, "Create presence tuple: parse timestamp failed");
                    Log.w(TAG, "Create presence tuple: parse timestamp failed");
                }
                }
            }
            }

            return rcsContactPresenceTupleBuilder.build();
            return rcsContactPresenceTupleBuilder.build();
        } else {
            return null;
        }
    }
    }


    private boolean isCapabilityExpired(Cursor cursor) {
    private boolean isCapabilityExpired(Cursor cursor) {
@@ -570,8 +577,28 @@ public class EabControllerImpl implements EabController {
        int commonId = Integer.parseInt(result.getLastPathSegment());
        int commonId = Integer.parseInt(result.getLastPathSegment());
        Log.d(TAG, "Insert into common table. Id: " + commonId);
        Log.d(TAG, "Insert into common table. Id: " + commonId);


        if (capability.getCapabilityTuples().size() == 0) {
            insertEmptyTuple(commonId);
        } else {
            insertAllTuples(commonId, capability);
        }
    }

    private void insertEmptyTuple(int commonId) {
        Log.d(TAG, "Insert empty tuple into presence table.");
        ContentValues contentValues = new ContentValues();
        contentValues.put(EabProvider.PresenceTupleColumns.EAB_COMMON_ID, commonId);
        // Using current timestamp instead of network timestamp since there is not use cases for
        // network timestamp and the network timestamp may cause capability expire immediately.
        contentValues.put(EabProvider.PresenceTupleColumns.REQUEST_TIMESTAMP,
                mExpirationTimeFactory.getExpirationTime());
        mContext.getContentResolver().insert(EabProvider.PRESENCE_URI, contentValues);
    }

    private void insertAllTuples(int commonId, RcsContactUceCapability capability) {
        ContentValues[] presenceContent =
        ContentValues[] presenceContent =
                new ContentValues[capability.getCapabilityTuples().size()];
                new ContentValues[capability.getCapabilityTuples().size()];

        for (int i = 0; i < presenceContent.length; i++) {
        for (int i = 0; i < presenceContent.length; i++) {
            RcsContactPresenceTuple tuple = capability.getCapabilityTuples().get(i);
            RcsContactPresenceTuple tuple = capability.getCapabilityTuples().get(i);


@@ -592,7 +619,7 @@ public class EabControllerImpl implements EabController {
                }
                }
            }
            }


            contentValues = new ContentValues();
            ContentValues contentValues = new ContentValues();
            contentValues.put(EabProvider.PresenceTupleColumns.EAB_COMMON_ID, commonId);
            contentValues.put(EabProvider.PresenceTupleColumns.EAB_COMMON_ID, commonId);
            contentValues.put(EabProvider.PresenceTupleColumns.BASIC_STATUS, tuple.getStatus());
            contentValues.put(EabProvider.PresenceTupleColumns.BASIC_STATUS, tuple.getStatus());
            contentValues.put(EabProvider.PresenceTupleColumns.SERVICE_ID, tuple.getServiceId());
            contentValues.put(EabProvider.PresenceTupleColumns.SERVICE_ID, tuple.getServiceId());
+60 −1
Original line number Original line Diff line number Diff line
@@ -35,7 +35,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.net.Uri;
import android.os.Looper;
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.PersistableBundle;
import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.RcsContactPresenceTuple;
import android.telephony.ims.RcsContactPresenceTuple;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsContactUceCapability;
import android.test.mock.MockContentResolver;
import android.test.mock.MockContentResolver;
@@ -317,6 +316,59 @@ public class EabControllerTest extends ImsTestBase {
                mEabControllerSub2.getCapabilities(contactUriList).size());
                mEabControllerSub2.getCapabilities(contactUriList).size());
    }
    }


    @Test
    @SmallTest
    public void testSaveCapabilityWithEmptyTuple() {
        List<RcsContactUceCapability> contactList = new ArrayList<>();
        contactList.add(createEmptyTuplePresenceCapability());

        mEabControllerSub1.saveCapabilities(contactList);

        List<Uri> contactUriList = new ArrayList<>();
        contactUriList.add(TEST_CONTACT_URI);
        List<EabCapabilityResult> capabilityResults =
                mEabControllerSub1.getCapabilities(contactUriList);
        Assert.assertEquals(1, capabilityResults.size());
        Assert.assertEquals(EabCapabilityResult.EAB_QUERY_SUCCESSFUL,
                capabilityResults.get(0).getStatus());
        Assert.assertEquals(0,
                capabilityResults.get(0).getContactCapabilities().getCapabilityTuples().size());
    }

    @Test
    @SmallTest
    public void testGetCapabilityWithEmptyTuple() {
        List<RcsContactUceCapability> contactList = new ArrayList<>();
        contactList.add(createEmptyTuplePresenceCapability());

        mEabControllerSub1.saveCapabilities(contactList);

        List<Uri> contactUriList = new ArrayList<>();
        contactUriList.add(TEST_CONTACT_URI);
        Assert.assertEquals(1,
                mEabControllerSub1.getCapabilities(contactUriList).size());
        Assert.assertEquals(EabCapabilityResult.EAB_QUERY_SUCCESSFUL,
                mEabControllerSub1.getCapabilities(contactUriList).get(0).getStatus());
    }

    @Test
    @SmallTest
    public void testGetExpiredCapabilityWithEmptyTuple() {
        List<RcsContactUceCapability> contactList = new ArrayList<>();
        doReturn(0L).when(mExpirationTimeFactory).getExpirationTime();

        contactList.add(createEmptyTuplePresenceCapability());

        mEabControllerSub1.saveCapabilities(contactList);

        List<Uri> contactUriList = new ArrayList<>();
        contactUriList.add(TEST_CONTACT_URI);
        Assert.assertEquals(1,
                mEabControllerSub1.getCapabilities(contactUriList).size());
        Assert.assertEquals(EabCapabilityResult.EAB_CONTACT_EXPIRED_FAILURE,
                mEabControllerSub1.getCapabilities(contactUriList).get(0).getStatus());
    }

    private RcsContactUceCapability createPresenceCapability() {
    private RcsContactUceCapability createPresenceCapability() {
        RcsContactPresenceTuple.ServiceCapabilities.Builder serviceCapabilitiesBuilder =
        RcsContactPresenceTuple.ServiceCapabilities.Builder serviceCapabilitiesBuilder =
                new RcsContactPresenceTuple.ServiceCapabilities.Builder(TEST_AUDIO_CAPABLE,
                new RcsContactPresenceTuple.ServiceCapabilities.Builder(TEST_AUDIO_CAPABLE,
@@ -363,6 +415,13 @@ public class EabControllerTest extends ImsTestBase {
        return builder.build();
        return builder.build();
    }
    }


    private RcsContactUceCapability createEmptyTuplePresenceCapability() {
        RcsContactUceCapability.PresenceBuilder builder =
                new RcsContactUceCapability.PresenceBuilder(
                        TEST_CONTACT_URI, SOURCE_TYPE_NETWORK, REQUEST_RESULT_FOUND);
        return builder.build();
    }

    private void insertContactInfoToDB() {
    private void insertContactInfoToDB() {
        ContentValues data = new ContentValues();
        ContentValues data = new ContentValues();
        data.put(EabProvider.ContactColumns.PHONE_NUMBER, TEST_PHONE_NUMBER);
        data.put(EabProvider.ContactColumns.PHONE_NUMBER, TEST_PHONE_NUMBER);