blob: af52217d5ca955961715e646e7bed80e338478f6 [file] [log] [blame]
/*
* Copyright (C) 2020 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.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;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.ims.ImsTestBase;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.time.temporal.ChronoUnit;
import java.time.Instant;
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";
private static final String TEST_SERVICE_STATUS = "status";
private static final String TEST_SERVICE_SERVICE_ID = "serviceId";
private static final String TEST_SERVICE_VERSION = "version";
private static final String TEST_SERVICE_DESCRIPTION = "description";
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
public void setUp() throws Exception {
super.setUp();
MockContentResolver mockContentResolver =
(MockContentResolver) mContext.getContentResolver();
mEabProviderTestable.initializeForTesting(mContext);
mockContentResolver.addProvider(EabProvider.AUTHORITY, mEabProviderTestable);
insertContactInfoToDB();
mEabController = new EabControllerImpl(
mContext, TEST_SUB_ID, null, Looper.getMainLooper());
mBundle = mContextFixture.getTestCarrierConfigBundle();
}
@After
public void tearDown() throws Exception {
super.tearDown();
}
@Test
@SmallTest
public void testGetAvailability() {
List<RcsContactUceCapability> contactList = new ArrayList<>();
contactList.add(createPresenceCapability(false));
mEabController.saveCapabilities(contactList);
EabCapabilityResult result = mEabController.getAvailability(TEST_CONTACT_URI);
Assert.assertEquals(EabCapabilityResult.EAB_QUERY_SUCCESSFUL, result.getStatus());
Assert.assertEquals(TEST_CONTACT_URI,
result.getContactCapabilities().getContactUri());
}
@Test
@SmallTest
public void testGetCapability() {
List<RcsContactUceCapability> contactList = new ArrayList<>();
contactList.add(createPresenceCapability(false));
mEabController.saveCapabilities(contactList);
List<Uri> contactUriList = new ArrayList<>();
contactUriList.add(TEST_CONTACT_URI);
Assert.assertEquals(1,
mEabController.getCapabilities(contactUriList).size());
Assert.assertEquals(EabCapabilityResult.EAB_QUERY_SUCCESSFUL,
mEabController.getCapabilities(contactUriList).get(0).getStatus());
}
@Test
@SmallTest
public void testGetExpiredCapability() {
List<RcsContactUceCapability> contactList = new ArrayList<>();
contactList.add(createPresenceCapability(true));
mEabController.saveCapabilities(contactList);
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 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);
List<RcsContactUceCapability> contactList = new ArrayList<>();
contactList.add(createPresenceNonRcsCapability(Instant.now()));
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
Instant timestamp = Instant.now().minus(120, ChronoUnit.DAYS);
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) {
Instant timestamp;
if (isExpired) {
timestamp = Instant.now().minus(120, ChronoUnit.DAYS);
} else {
timestamp = Instant.now().plus(120, ChronoUnit.DAYS);
}
RcsContactPresenceTuple.ServiceCapabilities.Builder serviceCapabilitiesBuilder =
new RcsContactPresenceTuple.ServiceCapabilities.Builder(TEST_AUDIO_CAPABLE,
TEST_VIDEO_CAPABLE);
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())
.setTime(timestamp)
.build();
RcsContactPresenceTuple tupleWithEmptyServiceCapabilities =
new RcsContactPresenceTuple.Builder(TEST_SERVICE_STATUS, TEST_SERVICE_SERVICE_ID,
TEST_SERVICE_VERSION)
.setServiceDescription(TEST_SERVICE_DESCRIPTION)
.setContactUri(TEST_CONTACT_URI)
.setTime(timestamp)
.build();
RcsContactUceCapability.PresenceBuilder builder =
new RcsContactUceCapability.PresenceBuilder(
TEST_CONTACT_URI, SOURCE_TYPE_NETWORK, REQUEST_RESULT_FOUND);
builder.addCapabilityTuple(tupleWithServiceCapabilities);
builder.addCapabilityTuple(tupleWithEmptyServiceCapabilities);
return builder.build();
}
private RcsContactUceCapability createPresenceNonRcsCapability(Instant 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())
.setTime(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);
data.put(EabProvider.ContactColumns.RAW_CONTACT_ID, 1);
mContext.getContentResolver().insert(CONTACT_URI, data);
}
}