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

Commit d9d88b54 authored by Calvin Pan's avatar Calvin Pan Committed by Gerrit Code Review
Browse files

Merge changes from topic "non_rcs_capabilities_expiration"

* changes:
  Clean up invalid capabilities when save capabilities
  Use non RCS capabilities cache expiration when result is not found
parents 3a620435 4a09faec
Loading
Loading
Loading
Loading
+162 −5
Original line number Diff line number Diff line
@@ -18,14 +18,21 @@ package com.android.ims.rcs.uce.eab;

import static android.telephony.ims.RcsContactUceCapability.CAPABILITY_MECHANISM_OPTIONS;
import static android.telephony.ims.RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE;
import static android.telephony.ims.RcsContactUceCapability.REQUEST_RESULT_NOT_FOUND;
import static android.telephony.ims.RcsContactUceCapability.SOURCE_TYPE_CACHED;

import static com.android.ims.rcs.uce.eab.EabProvider.EAB_OPTIONS_TABLE_NAME;
import static com.android.ims.rcs.uce.eab.EabProvider.EAB_PRESENCE_TUPLE_TABLE_NAME;

import android.annotation.NonNull;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.RcsContactPresenceTuple;
import android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities;
@@ -39,6 +46,7 @@ import android.util.TimeFormatException;

import com.android.ims.RcsFeatureManager;
import com.android.ims.rcs.uce.UceController.UceControllerCallback;
import com.android.internal.annotations.VisibleForTesting;

import java.time.Instant;
import java.time.temporal.ChronoUnit;
@@ -46,6 +54,7 @@ import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Objects;
import java.util.TimeZone;
import java.util.function.Predicate;

/**
@@ -58,17 +67,29 @@ public class EabControllerImpl implements EabController {
    private static final int DEFAULT_CAPABILITY_CACHE_EXPIRATION_SEC = 90 * 24 * 60 * 60;
    private static final int DEFAULT_AVAILABILITY_CACHE_EXPIRATION_SEC = 60;

    // 1 week
    private static final int CLEAN_UP_LEGACY_CAPABILITY_SEC = 7 * 24 * 60 * 60;
    private static final int CLEAN_UP_LEGACY_CAPABILITY_DELAY_MILLI_SEC = 30 * 1000;

    private final Context mContext;
    private final int mSubId;
    private final EabBulkCapabilityUpdater mEabBulkCapabilityUpdater;
    private final Handler mHandler;

    private UceControllerCallback mUceControllerCallback;
    private volatile boolean mIsSetDestroyedFlag = false;

    @VisibleForTesting
    public final Runnable mCapabilityCleanupRunnable = () -> {
        Log.d(TAG, "Cleanup Capabilities");
        cleanupExpiredCapabilities();
    };

    public EabControllerImpl(Context context, int subId, UceControllerCallback c, Looper looper) {
        mContext = context;
        mSubId = subId;
        mUceControllerCallback = c;
        mHandler = new Handler(looper);
        mEabBulkCapabilityUpdater = new EabBulkCapabilityUpdater(mContext, mSubId,
                this,
                new EabContactSyncController(),
@@ -190,6 +211,12 @@ public class EabControllerImpl implements EabController {
        }

        mEabBulkCapabilityUpdater.updateExpiredTimeAlert();

        if (mHandler.hasCallbacks(mCapabilityCleanupRunnable)) {
            mHandler.removeCallbacks(mCapabilityCleanupRunnable);
        }
        mHandler.postDelayed(mCapabilityCleanupRunnable,
                CLEAN_UP_LEGACY_CAPABILITY_DELAY_MILLI_SEC);
    }

    private List<EabCapabilityResult> generateDestroyedResult(List<Uri> contactUri) {
@@ -358,20 +385,34 @@ public class EabControllerImpl implements EabController {
    private boolean isCapabilityExpired(Cursor cursor) {
        boolean expired = false;
        String requestTimeStamp = getRequestTimestamp(cursor);
        int capabilityCacheExpiration;

        if (isNonRcsCapability(cursor)) {
            capabilityCacheExpiration = getNonRcsCapabilityCacheExpiration(mSubId);
        } else {
            capabilityCacheExpiration = getCapabilityCacheExpiration(mSubId);
        }

        if (requestTimeStamp != null) {
            Instant expiredTimestamp = Instant
                    .ofEpochSecond(Long.parseLong(requestTimeStamp))
                    .plus(getCapabilityCacheExpiration(mSubId), ChronoUnit.SECONDS);
                    .plus(capabilityCacheExpiration, ChronoUnit.SECONDS);
            expired = expiredTimestamp.isBefore(Instant.now());
            Log.d(TAG, "Capability expiredTimestamp: "
                    + expiredTimestamp.getEpochSecond() + ", expired:" + expired);
            Log.d(TAG, "Capability expiredTimestamp: " + expiredTimestamp.getEpochSecond() +
                    ", isNonRcsCapability: " +  isNonRcsCapability(cursor) +
                    ", capabilityCacheExpiration: " + capabilityCacheExpiration +
                    ", expired:" + expired);
        } else {
            Log.d(TAG, "Capability requestTimeStamp is null");
        }
        return expired;
    }

    private boolean isNonRcsCapability(Cursor cursor) {
        int result = getIntValue(cursor, EabProvider.EabCommonColumns.REQUEST_RESULT);
        return result == REQUEST_RESULT_NOT_FOUND;
    }

    private boolean isAvailabilityExpired(Cursor cursor) {
        boolean expired = false;
        String requestTimeStamp = getRequestTimestamp(cursor);
@@ -402,8 +443,24 @@ public class EabControllerImpl implements EabController {
        return expiredTimestamp;
    }

    protected static long getCapabilityCacheExpiration(int subId) {
        long value = -1;
    private int getNonRcsCapabilityCacheExpiration(int subId) {
        int value;
        PersistableBundle carrierConfig =
                mContext.getSystemService(CarrierConfigManager.class).getConfigForSubId(subId);

        if (carrierConfig != null) {
            value = carrierConfig.getInt(
                    CarrierConfigManager.Ims.KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT);
        } else {
            value = DEFAULT_CAPABILITY_CACHE_EXPIRATION_SEC;
            Log.e(TAG, "getNonRcsCapabilityCacheExpiration: " +
                    "CarrierConfig is null, returning default");
        }
        return value;
    }

    protected static int getCapabilityCacheExpiration(int subId) {
        int value = -1;
        try {
            ProvisioningManager pm = ProvisioningManager.createForSubscriptionId(subId);
            value = pm.getProvisioningIntValue(
@@ -508,6 +565,7 @@ public class EabControllerImpl implements EabController {
                    GregorianCalendar date = new GregorianCalendar(
                            time.year, time.month, time.monthDay,
                            time.hour, time.minute, time.second);
                    date.setTimeZone(TimeZone.getTimeZone("UTC"));
                    timestamp = date.getTime().getTime() / 1000;
                } catch (TimeFormatException ex) {
                    Log.d(TAG, "Fail on parsing the timestamp. "
@@ -592,6 +650,105 @@ public class EabControllerImpl implements EabController {
        mContext.getContentResolver().bulkInsert(EabProvider.OPTIONS_URI, optionContent);
    }

    private void cleanupExpiredCapabilities() {
        // Cleanup the capabilities that expired more than 1 week
        long rcsCapabilitiesExpiredTime = Instant.now().getEpochSecond() -
                getCapabilityCacheExpiration(mSubId) -
                CLEAN_UP_LEGACY_CAPABILITY_SEC;

        // Cleanup the capabilities that expired more than 1 week
        long nonRcsCapabilitiesExpiredTime = Instant.now().getEpochSecond() -
                getNonRcsCapabilityCacheExpiration(mSubId) -
                CLEAN_UP_LEGACY_CAPABILITY_SEC;

        cleanupCapabilities(rcsCapabilitiesExpiredTime, getRcsCommonIdList());
        cleanupCapabilities(nonRcsCapabilitiesExpiredTime, getNonRcsCommonIdList());
        cleanupOrphanedRows();
    }

    private void cleanupCapabilities(long rcsCapabilitiesExpiredTime, List<Integer> commonIdList) {
        if (commonIdList.size() > 0) {
            String presenceClause =
                    EabProvider.PresenceTupleColumns.EAB_COMMON_ID +
                            " IN (" + TextUtils.join(",", commonIdList) + ") " + " AND " +
                            EabProvider.PresenceTupleColumns.REQUEST_TIMESTAMP + "<?";

            String optionClause =
                    EabProvider.PresenceTupleColumns.EAB_COMMON_ID +
                            " IN (" + TextUtils.join(",", commonIdList) + ") " + " AND " +
                            EabProvider.OptionsColumns.REQUEST_TIMESTAMP + "<?";

            int deletePresenceCount = mContext.getContentResolver().delete(
                    EabProvider.PRESENCE_URI,
                    presenceClause,
                    new String[]{String.valueOf(rcsCapabilitiesExpiredTime)});

            int deleteOptionsCount = mContext.getContentResolver().delete(
                    EabProvider.OPTIONS_URI,
                    optionClause,
                    new String[]{String.valueOf(rcsCapabilitiesExpiredTime)});

            Log.d(TAG, "Cleanup capabilities. deletePresenceCount: " + deletePresenceCount +
                ",deleteOptionsCount: " + deleteOptionsCount);
        }
    }

    private List<Integer> getRcsCommonIdList() {
        ArrayList<Integer> list = new ArrayList<>();
        Cursor cursor = mContext.getContentResolver().query(
                EabProvider.COMMON_URI,
                null,
                EabProvider.EabCommonColumns.REQUEST_RESULT + "<>?",
                new String[]{String.valueOf(REQUEST_RESULT_NOT_FOUND)},
                null);

        if (cursor == null) return list;

        while (cursor.moveToNext()) {
            list.add(cursor.getInt(cursor.getColumnIndex(EabProvider.EabCommonColumns._ID)));
        }
        cursor.close();

        return list;
    }

    private List<Integer> getNonRcsCommonIdList() {
        ArrayList<Integer> list = new ArrayList<>();
        Cursor cursor = mContext.getContentResolver().query(
                EabProvider.COMMON_URI,
                null,
                EabProvider.EabCommonColumns.REQUEST_RESULT + "=?",
                new String[]{String.valueOf(REQUEST_RESULT_NOT_FOUND)},
                null);

        if (cursor == null) return list;

        while (cursor.moveToNext()) {
            list.add(cursor.getInt(cursor.getColumnIndex(EabProvider.EabCommonColumns._ID)));
        }
        cursor.close();

        return list;
    }

    /**
     * Cleanup the entry of common table that can't map to presence or option table
     */
    private void cleanupOrphanedRows() {
        String presenceSelection =
                " (SELECT " + EabProvider.PresenceTupleColumns.EAB_COMMON_ID +
                        " FROM " + EAB_PRESENCE_TUPLE_TABLE_NAME + ") ";
        String optionSelection =
                " (SELECT " + EabProvider.OptionsColumns.EAB_COMMON_ID +
                        " FROM " + EAB_OPTIONS_TABLE_NAME + ") ";

        mContext.getContentResolver().delete(
                EabProvider.COMMON_URI,
                EabProvider.EabCommonColumns._ID + " NOT IN " + presenceSelection +
                        " AND " + EabProvider.EabCommonColumns._ID+ " NOT IN " + optionSelection,
                null);
    }

    private String getStringValue(Cursor cursor, String column) {
        return cursor.getString(cursor.getColumnIndex(column));
    }
+4 −4
Original line number Diff line number Diff line
@@ -83,10 +83,10 @@ public class EabProvider extends ContentProvider {
    private static final String TAG = "EabProvider";
    private static final int DATABASE_VERSION = 2;

    private static final String EAB_CONTACT_TABLE_NAME = "eab_contact";
    private static final String EAB_COMMON_TABLE_NAME = "eab_common";
    private static final String EAB_PRESENCE_TUPLE_TABLE_NAME = "eab_presence";
    private static final String EAB_OPTIONS_TABLE_NAME = "eab_options";
    public static final String EAB_CONTACT_TABLE_NAME = "eab_contact";
    public static final String EAB_COMMON_TABLE_NAME = "eab_common";
    public static final String EAB_PRESENCE_TUPLE_TABLE_NAME = "eab_presence";
    public static final String EAB_OPTIONS_TABLE_NAME = "eab_options";

    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
    private static final int URL_CONTACT = 1;
+186 −4
Original line number Diff line number Diff line
@@ -16,14 +16,24 @@

package com.android.ims.rcs.uce.eab;

import static android.telephony.CarrierConfigManager.Ims.KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT;
import static android.telephony.ims.RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE;
import static android.telephony.ims.RcsContactUceCapability.REQUEST_RESULT_FOUND;
import static android.telephony.ims.RcsContactUceCapability.REQUEST_RESULT_NOT_FOUND;
import static android.telephony.ims.RcsContactUceCapability.SOURCE_TYPE_NETWORK;

import static com.android.ims.rcs.uce.eab.EabProvider.COMMON_URI;
import static com.android.ims.rcs.uce.eab.EabProvider.CONTACT_URI;
import static com.android.ims.rcs.uce.eab.EabProvider.OPTIONS_URI;
import static com.android.ims.rcs.uce.eab.EabProvider.PRESENCE_URI;

import static org.junit.Assert.fail;

import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.Looper;
import android.os.PersistableBundle;
import android.telephony.ims.RcsContactPresenceTuple;
import android.telephony.ims.RcsContactUceCapability;
import android.test.mock.MockContentResolver;
@@ -44,11 +54,17 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@RunWith(AndroidJUnit4.class)
public class EabControllerTest extends ImsTestBase {
    EabProviderTestable mEabProviderTestable = new EabProviderTestable();
    EabControllerImpl mEabController;
    PersistableBundle mBundle;
    ExecutorService mExecutor = Executors.newSingleThreadExecutor();

    private static final int TEST_SUB_ID = 1;
    private static final String TEST_PHONE_NUMBER = "16661234567";
@@ -59,6 +75,7 @@ public class EabControllerTest extends ImsTestBase {
    private static final boolean TEST_AUDIO_CAPABLE = true;
    private static final boolean TEST_VIDEO_CAPABLE = false;

    private static final int TIME_OUT_IN_SEC = 5;
    private static final Uri TEST_CONTACT_URI = Uri.parse(TEST_PHONE_NUMBER + "@android.test");

    @Before
@@ -72,6 +89,8 @@ public class EabControllerTest extends ImsTestBase {
        insertContactInfoToDB();
        mEabController = new EabControllerImpl(
                mContext, TEST_SUB_ID, null, Looper.getMainLooper());

        mBundle = mContextFixture.getTestCarrierConfigBundle();
    }

    @After
@@ -125,16 +144,160 @@ public class EabControllerTest extends ImsTestBase {
                mEabController.getCapabilities(contactUriList).get(0).getStatus());
    }

    @Test
    @SmallTest
    public void testNonRcsCapability() {
        // Set non-rcs capabilities expiration to 121 days
        mBundle.putInt(KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT, 121 * 24 * 60 * 60);
        // Set timestamp to 120 days age
        GregorianCalendar date = new GregorianCalendar();
        date.setTimeZone(TimeZone.getTimeZone("UTC"));
        date.add(Calendar.DATE, -120);
        String timestamp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
                .format(date.getTime());

        List<RcsContactUceCapability> contactList = new ArrayList<>();
        contactList.add(createPresenceNonRcsCapability(timestamp));

        mEabController.saveCapabilities(contactList);

        List<Uri> contactUriList = new ArrayList<>();
        contactUriList.add(TEST_CONTACT_URI);

        // Verify result is not expired
        Assert.assertEquals(1,
                mEabController.getCapabilities(contactUriList).size());
        Assert.assertEquals(EabCapabilityResult.EAB_QUERY_SUCCESSFUL,
                mEabController.getCapabilities(contactUriList).get(0).getStatus());
    }

    @Test
    @SmallTest
    public void testNonRcsCapabilityExpired() {
        // Set non-rcs capabilities expiration to 119 days
        mBundle.putInt(KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT, 119 * 24 * 60 * 60);
        // Set timestamp to 120 days age
        GregorianCalendar date = new GregorianCalendar();
        date.setTimeZone(TimeZone.getTimeZone("UTC"));
        date.add(Calendar.DATE, -120);
        String timestamp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
                .format(date.getTime());

        List<RcsContactUceCapability> contactList = new ArrayList<>();
        contactList.add(createPresenceNonRcsCapability(timestamp));
        mEabController.saveCapabilities(contactList);

        // Verify result is expired
        List<Uri> contactUriList = new ArrayList<>();
        contactUriList.add(TEST_CONTACT_URI);
        Assert.assertEquals(1,
                mEabController.getCapabilities(contactUriList).size());
        Assert.assertEquals(EabCapabilityResult.EAB_CONTACT_EXPIRED_FAILURE,
                mEabController.getCapabilities(contactUriList).get(0).getStatus());
    }

    @Test
    @SmallTest
    public void testCleanupInvalidDataInCommonTable() throws InterruptedException {
        // Insert invalid data in common table
        ContentValues data = new ContentValues();
        data.put(EabProvider.EabCommonColumns.EAB_CONTACT_ID, -1);
        data.put(EabProvider.EabCommonColumns.MECHANISM, CAPABILITY_MECHANISM_PRESENCE);
        data.put(EabProvider.EabCommonColumns.REQUEST_RESULT, REQUEST_RESULT_FOUND);
        data.put(EabProvider.EabCommonColumns.SUBSCRIPTION_ID, -1);
        mContext.getContentResolver().insert(COMMON_URI, data);

        mExecutor.execute(mEabController.mCapabilityCleanupRunnable);
        mExecutor.awaitTermination(TIME_OUT_IN_SEC, TimeUnit.SECONDS);

        // Verify the entry that cannot map to presence/option table has been removed
        Cursor cursor = mContext.getContentResolver().query(COMMON_URI, null, null, null, null);
        while(cursor.moveToNext()) {
            int contactId = cursor.getInt(
                    cursor.getColumnIndex(EabProvider.EabCommonColumns.EAB_CONTACT_ID));
            if (contactId == -1) {
                fail("Invalid data didn't been cleared");
            }
        }
    }

    @Test
    @SmallTest
    public void testCleanupInvalidDataInPresenceTable() throws InterruptedException {
        String expiredContact = "expiredContact";
        GregorianCalendar expiredDate = new GregorianCalendar();
        expiredDate.setTimeZone(TimeZone.getTimeZone("UTC"));
        expiredDate.add(Calendar.DATE, -120);
        // Insert invalid data in presence table
        ContentValues data = new ContentValues();
        data.put(EabProvider.EabCommonColumns.REQUEST_RESULT, REQUEST_RESULT_FOUND);
        Uri commonUri = mContext.getContentResolver().insert(COMMON_URI, data);

        data = new ContentValues();
        data.put(EabProvider.PresenceTupleColumns.EAB_COMMON_ID, commonUri.getLastPathSegment());
        data.put(EabProvider.PresenceTupleColumns.CONTACT_URI, expiredContact);
        data.put(EabProvider.PresenceTupleColumns.REQUEST_TIMESTAMP,
                expiredDate.getTime().getTime() / 1000);
        mContext.getContentResolver().insert(PRESENCE_URI, data);

        mExecutor.execute(mEabController.mCapabilityCleanupRunnable);
        mExecutor.awaitTermination(TIME_OUT_IN_SEC, TimeUnit.SECONDS);

        // Verify the invalid data has been removed after save capabilities
        Cursor cursor = mContext.getContentResolver().query(PRESENCE_URI, null, null, null, null);
        while(cursor.moveToNext()) {
            String contactUri = cursor.getString(
                    cursor.getColumnIndex(EabProvider.PresenceTupleColumns.CONTACT_URI));
            if (contactUri.equals(expiredContact)) {
                fail("Invalid data didn't been cleared");
            }
        }
    }

    @Test
    @SmallTest
    public void testCleanupInvalidDataInOptionTable() throws InterruptedException {
        String expiredFeatureTag = "expiredFeatureTag";
        GregorianCalendar expiredDate = new GregorianCalendar();
        expiredDate.setTimeZone(TimeZone.getTimeZone("UTC"));
        expiredDate.add(Calendar.DATE, -120);
        // Insert invalid data in presence table
        ContentValues data = new ContentValues();
        data.put(EabProvider.EabCommonColumns.REQUEST_RESULT, REQUEST_RESULT_NOT_FOUND);
        Uri commonUri = mContext.getContentResolver().insert(COMMON_URI, data);

        data = new ContentValues();
        data.put(EabProvider.PresenceTupleColumns.EAB_COMMON_ID, commonUri.getLastPathSegment());
        data.put(EabProvider.OptionsColumns.FEATURE_TAG, expiredFeatureTag);
        data.put(EabProvider.OptionsColumns.REQUEST_TIMESTAMP,
                expiredDate.getTime().getTime() / 1000);
        mContext.getContentResolver().insert(OPTIONS_URI, data);

        mExecutor.execute(mEabController.mCapabilityCleanupRunnable);
        mExecutor.awaitTermination(TIME_OUT_IN_SEC, TimeUnit.SECONDS);

        // Verify the invalid data has been removed after save capabilities
        Cursor cursor = mContext.getContentResolver().query(OPTIONS_URI, null, null, null, null);
        while(cursor.moveToNext()) {
            String featureTag = cursor.getString(
                    cursor.getColumnIndex(EabProvider.OptionsColumns.FEATURE_TAG));
            if (featureTag.equals(expiredFeatureTag)) {
                fail("Invalid data didn't been cleared");
            }
        }
    }

    private RcsContactUceCapability createPresenceCapability(boolean isExpired) {
        String timeStamp;
        String timestamp;
        GregorianCalendar date = new GregorianCalendar();
        date.setTimeZone(TimeZone.getTimeZone("UTC"));
        if (isExpired) {
            date.add(Calendar.DATE, -120);
        } else {
            date.add(Calendar.DATE, 120);
        }

        timeStamp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
        timestamp = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX")
                .format(date.getTime());

        RcsContactPresenceTuple.ServiceCapabilities.Builder serviceCapabilitiesBuilder =
@@ -146,7 +309,7 @@ public class EabControllerTest extends ImsTestBase {
                        .setServiceDescription(TEST_SERVICE_DESCRIPTION)
                        .setContactUri(TEST_CONTACT_URI)
                        .setServiceCapabilities(serviceCapabilitiesBuilder.build())
                        .setTimestamp(String.valueOf(timeStamp))
                        .setTimestamp(timestamp)
                        .build();

        RcsContactPresenceTuple tupleWithEmptyServiceCapabilities =
@@ -154,7 +317,7 @@ public class EabControllerTest extends ImsTestBase {
                        TEST_SERVICE_VERSION)
                        .setServiceDescription(TEST_SERVICE_DESCRIPTION)
                        .setContactUri(TEST_CONTACT_URI)
                        .setTimestamp(String.valueOf(timeStamp))
                        .setTimestamp(timestamp)
                        .build();

        RcsContactUceCapability.PresenceBuilder builder =
@@ -165,6 +328,25 @@ public class EabControllerTest extends ImsTestBase {
        return builder.build();
    }

    private RcsContactUceCapability createPresenceNonRcsCapability(String timestamp) {
        RcsContactPresenceTuple.ServiceCapabilities.Builder serviceCapabilitiesBuilder =
                new RcsContactPresenceTuple.ServiceCapabilities.Builder(false, false);
        RcsContactPresenceTuple tupleWithServiceCapabilities =
                new RcsContactPresenceTuple.Builder(TEST_SERVICE_STATUS, TEST_SERVICE_SERVICE_ID,
                        TEST_SERVICE_VERSION)
                        .setServiceDescription(TEST_SERVICE_DESCRIPTION)
                        .setContactUri(TEST_CONTACT_URI)
                        .setServiceCapabilities(serviceCapabilitiesBuilder.build())
                        .setTimestamp(timestamp)
                        .build();

        RcsContactUceCapability.PresenceBuilder builder =
                new RcsContactUceCapability.PresenceBuilder(
                        TEST_CONTACT_URI, SOURCE_TYPE_NETWORK, REQUEST_RESULT_NOT_FOUND);
        builder.addCapabilityTuple(tupleWithServiceCapabilities);
        return builder.build();
    }

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