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

Commit 545d699a authored by Calvin Pan's avatar Calvin Pan
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
Change-Id: Id54a71b71d353f3d2fa5c3246ab534ad581fe245
parent f9cc835d
Loading
Loading
Loading
Loading
+51 −23
Original line number Diff line number Diff line
@@ -320,7 +320,10 @@ public class EabControllerImpl implements EabController {
        if (mechanism == CAPABILITY_MECHANISM_PRESENCE) {
            PresenceBuilder builder = new PresenceBuilder(
                    contactUri, SOURCE_TYPE_CACHED, result);
            builder.addCapabilityTuple(createPresenceTuple(contactUri, cursor));
            RcsContactPresenceTuple tuple = createPresenceTuple(contactUri, cursor);
            if (tuple != null) {
                builder.addCapabilityTuple(tuple);
            }
            builderWrapper.setPresenceBuilder(builder);
        } else {
            OptionsBuilder builder = new OptionsBuilder(contactUri, SOURCE_TYPE_CACHED);
@@ -382,6 +385,9 @@ public class EabControllerImpl implements EabController {
        serviceCapabilities = serviceCapabilitiesBuilder.build();

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

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

    private boolean isCapabilityExpired(Cursor cursor) {
@@ -558,8 +566,28 @@ public class EabControllerImpl implements EabController {
        int commonId = Integer.parseInt(result.getLastPathSegment());
        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 =
                new ContentValues[capability.getCapabilityTuples().size()];

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

@@ -580,7 +608,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.BASIC_STATUS, tuple.getStatus());
            contentValues.put(EabProvider.PresenceTupleColumns.SERVICE_ID, tuple.getServiceId());
+60 −1
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Looper;
import android.os.PersistableBundle;
import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.RcsContactPresenceTuple;
import android.telephony.ims.RcsContactUceCapability;
import android.test.mock.MockContentResolver;
@@ -313,6 +312,59 @@ public class EabControllerTest extends ImsTestBase {
                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() {
        RcsContactPresenceTuple.ServiceCapabilities.Builder serviceCapabilitiesBuilder =
                new RcsContactPresenceTuple.ServiceCapabilities.Builder(TEST_AUDIO_CAPABLE,
@@ -358,6 +410,13 @@ public class EabControllerTest extends ImsTestBase {
        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() {
        ContentValues data = new ContentValues();
        data.put(EabProvider.ContactColumns.PHONE_NUMBER, TEST_PHONE_NUMBER);