1 /* 2 * Copyright 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.telephony.ims; 18 19 import static junit.framework.Assert.assertEquals; 20 import static junit.framework.Assert.assertFalse; 21 import static junit.framework.Assert.assertNotNull; 22 import static junit.framework.Assert.assertNull; 23 import static junit.framework.Assert.assertTrue; 24 25 import static org.mockito.Mockito.when; 26 27 import android.content.ContentValues; 28 import android.content.Context; 29 import android.telephony.SubscriptionManager; 30 import android.telephony.ims.RcsConfig; 31 import android.telephony.ims.RcsConfig.Characteristic; 32 import android.test.mock.MockContentResolver; 33 34 import androidx.test.ext.junit.runners.AndroidJUnit4; 35 import androidx.test.filters.SmallTest; 36 37 import com.android.internal.telephony.FakeTelephonyProvider; 38 39 import org.junit.After; 40 import org.junit.Before; 41 import org.junit.Test; 42 import org.junit.runner.RunWith; 43 import org.mockito.Mock; 44 import org.mockito.MockitoAnnotations; 45 46 import java.util.Arrays; 47 48 @RunWith(AndroidJUnit4.class) 49 public final class RcsConfigTest { 50 51 private static final String TEST_RCS_CONFIG = "<?xml version=\"1.0\"?>\n" 52 + "<wap-provisioningdoc version=\"1.1\">\n" 53 + "\t<characteristic type=\"APPLICATION\">\n" 54 + "\t\t<parm name=\"AppID\" value=\"urn:oma:mo:ext-3gpp-ims:1.0\"/>\n" 55 + "\t\t<characteristic type=\"3GPP_IMS\">\n" 56 + "\t\t\t<parm name=\"AppID\" value=\"ap2001\"/>\n" 57 + "\t\t\t<parm name=\"Name\" value=\"RCS IMS Settings\"/>\n" 58 + "\t\t\t<characteristic type=\"Ext\">\n" 59 + "\t\t\t\t<characteristic type=\"GSMA\">\n" 60 + "\t\t\t\t\t<parm name=\"AppRef\" value=\"IMS-Setting\"/>\n" 61 + "\t\t\t\t\t<parm name=\"rcsVolteSingleRegistration\" value=\"1\"/>\n" 62 + "\t\t\t\t</characteristic>\n" 63 + "\t\t\t</characteristic>\n" 64 + "\t\t</characteristic>\n" 65 + "\t\t<characteristic type=\"SERVICES\">\n" 66 + "\t\t\t<parm name=\"SupportedRCSProfileVersions\" value=\"UP_2.3\"/>\n" 67 + "\t\t\t<parm name=\"ChatAuth\" value=\"1\"/>\n" 68 + "\t\t\t<parm name=\"GroupChatAuth\" value=\"1\"/>\n" 69 + "\t\t\t<parm name=\"ftAuth\" value=\"1\"/>\n" 70 + "\t\t\t<parm name=\"standaloneMsgAuth\" value=\"1\"/>\n" 71 + "\t\t\t<parm name=\"geolocPushAuth\" value=\"1\"/>\n" 72 + "\t\t\t<characteristic type=\"Ext\">\n" 73 + "\t\t\t\t<characteristic type=\"DataOff\">\n" 74 + "\t\t\t\t\t<parm name=\"rcsMessagingDataOff\" value=\"1\"/>\n" 75 + "\t\t\t\t\t<parm name=\"fileTransferDataOff\" value=\"1\"/>\n" 76 + "\t\t\t\t\t<parm name=\"mmsDataOff\" value=\"1\"/>\n" 77 + "\t\t\t\t\t<parm name=\"syncDataOff\" value=\"1\"/>\n" 78 + "\t\t\t\t\t<characteristic type=\"Ext\"/>\n" 79 + "\t\t\t\t</characteristic>\n" 80 + "\t\t\t</characteristic>\n" 81 + "\t\t</characteristic>\n" 82 + "\t\t<characteristic type=\"PRESENCE\">\n" 83 + "\t\t\t<parm name=\"client-obj-datalimit\" value=\"8192\"/>\n" 84 + "\t\t\t<parm name=\"content-serveruri\" value=\"X\"/>\n" 85 + "\t\t\t<parm name=\"source-throttlepublish\" value=\"32\"/>\n" 86 + "\t\t\t<parm name=\"max-number-ofsubscriptions-inpresence-list\" value=\"8\"/>\n" 87 + "\t\t\t<parm name=\"service-uritemplate\" value=\"X\"/>\n" 88 + "\t\t\t<parm name=\"RLS-URI\" value=\"X\"/>\n" 89 + "\t\t</characteristic>\n" 90 + "\t\t<characteristic type=\"MESSAGING\">\n" 91 + "\t\t\t<characteristic type=\"StandaloneMsg\">\n" 92 + "\t\t\t\t<parm name=\"MaxSize\" value=\"8192\"/>\n" 93 + "\t\t\t\t<parm name=\"SwitchoverSize\" value=\"1024\"/>\n" 94 + "\t\t\t\t<parm name=\"exploder-uri\" value=\"X\"/>\n" 95 + "\t\t\t</characteristic>\n" 96 + "\t\t\t<characteristic type=\"Chat\">\n" 97 + "\t\t\t\t<parm name=\"max_adhoc_group_size\" value=\"60\"/>\n" 98 + "\t\t\t\t<parm name=\"conf-fcty-uri\" value=\"X\"/>\n" 99 + "\t\t\t\t<parm name=\"AutAccept\" value=\"1\"/>\n" 100 + "\t\t\t\t<parm name=\"AutAcceptGroupChat\" value=\"1\"/>\n" 101 + "\t\t\t\t<parm name=\"TimerIdle\" value=\"120\"/>\n" 102 + "\t\t\t\t<parm name=\"MaxSize\" value=\"16384\"/>\n" 103 + "\t\t\t\t<parm name=\"ChatRevokeTimer\" value=\"0\"/>\n" 104 + "\t\t\t\t<parm name=\"reconnectGuardTimer\" value=\"0\"/>\n" 105 + "\t\t\t\t<parm name=\"cfsTrigger\" value=\"1\"/>\n" 106 + "\t\t\t</characteristic>\n" 107 + "\t\t\t<parm name=\"max1ToManyRecipients\" value=\"8\"/>\n" 108 + "\t\t\t<parm name=\"1toManySelectedTech\" value=\"1\"/>\n" 109 + "\t\t\t<parm name=\"displayNotificationSwitch\" value=\"0\"/>\n" 110 + "\t\t\t<parm name=\"contentCompressSize\" value=\"1024\"/>\n" 111 + "\t\t\t<characteristic type=\"FileTransfer\">\n" 112 + "\t\t\t\t<parm name=\"ftWarnSize\" value=\"0\"/>\n" 113 + "\t\t\t\t<parm name=\"MaxSizeFileTr\" value=\"65536\"/>\n" 114 + "\t\t\t\t<parm name=\"ftAutAccept\" value=\"1\"/>\n" 115 + "\t\t\t\t<parm name=\"ftHTTPCSURI\" value=\"X\"/>\n" 116 + "\t\t\t\t<parm name=\"ftHTTPDLURI\" value=\"X\"/>\n" 117 + "\t\t\t\t<parm name=\"ftHTTPCSUser\" value=\"X\"/>\n" 118 + "\t\t\t\t<parm name=\"ftHTTPCSPwd\" value=\"X\"/>\n" 119 + "\t\t\t\t<parm name=\"ftHTTPFallback\" value=\"X\"/>\n" 120 + "\t\t\t\t<parm name=\" ftMax1ToManyRecipients\" value=\"0\"/>\n" 121 + "\t\t\t</characteristic>\n" 122 + "\t\t\t<characteristic type=\"Chatbot\">\n" 123 + "\t\t\t\t<parm name=\"ChatbotDirectory\" value=\"X\"/>\n" 124 + "\t\t\t\t<parm name=\"BotinfoFQDNRoot\" value=\"X\"/>\n" 125 + "\t\t\t\t<part name=\"SpecificChatbotsList\" value=\"X\"/>\n" 126 + "\t\t\t\t<parm name=\"IdentityInEnrichedSearch\" value=\"1\"/>\n" 127 + "\t\t\t\t<parm name=\"PrivacyDisable\" value=\"0\"/>\n" 128 + "\t\t\t\t<parm name=\"ChatbotMsgTech\" value=\"1\"/>\n" 129 + "\t\t\t</characteristic>\n" 130 + "\t\t\t<characteristic type=\"MessageStore\">\n" 131 + "\t\t\t\t<parm name=\"MsgStoreUrl\" value=\"X\"/>\n" 132 + "\t\t\t\t<parm name=\"MsgStoreNotifUrl\" value=\"X\"/>\n" 133 + "\t\t\t\t<parm name=\"MsgStoreAuth\" value=\"X\"/>\n" 134 + "\t\t\t\t<parm name=\"MsgStoreUserName\" value=\"X\"/>\n" 135 + "\t\t\t\t<parm name=\"MsgStoreUserPwd\" value=\"X\"/>\n" 136 + "\t\t\t\t<parm name=\"EventRpting\" value=\"1\"/>\n" 137 + "\t\t\t\t<parm name=\"AuthArchive\" value=\"1\"/>\n" 138 + "\t\t\t\t<parm name=\"SMSStore\" value=\"1\"/>\n" 139 + "\t\t\t\t<parm name=\"MMSStore\" value=\"1\"/>\n" 140 + "\t\t\t</characteristic>\n" 141 + "\t\t\t<characteristic type=\"Ext\"/>\n" 142 + "\t\t</characteristic>\n" 143 + "\t</characteristic>\n" 144 + "</wap-provisioningdoc>\n"; 145 146 private static final String[][] TEST_CONFIG_VALUES = {{"rcsVolteSingleRegistration", "1"}, 147 {"SupportedRCSProfileVersions", "UP_2.3"}, {"ChatAuth", "1"}, {"GroupChatAuth", "1"}, 148 {"ftAuth", "1"}, {"standaloneMsgAuth", "1"}, {"geolocPushAuth", "1"}, 149 {"rcsMessagingDataOff", "1"}, {"fileTransferDataOff", "1"}, {"mmsDataOff", "1"}, 150 {"syncDataOff", "1"}}; 151 152 private static final String[] VALID_CHARACTERISTICS = {"APPLICATION", "3GPP_IMS", "Ext", 153 "GSMA", "SERVICES", "DaTAOFF", "PRESENCE", "MESSAGING", "Chat", "FileTransfer", 154 "Chatbot", "MessageSTORE"}; 155 private static final String[] INVALID_CHARACTERISTICS = {"APP2LICATION", "3GPPIMS", "Exte", 156 "GSMf", "SERVICE", "DaTAOn", "PRESENCE2", "MESSAG", "Ch", "File", "STORE"}; 157 private static final String[][] SUB_CHARACTERISTICS = { 158 {"APPLICATION", "3GPP_IMS", "Ext", "GSMA"}, 159 {"APPLICATION", "SERVICES", "Ext", "DataOff", "Ext"}}; 160 private static final String[][] SAME_PARMS_DIFF_CHARS_VALUE_MAP = { 161 {"MaxSize", "Chat", "16384"}, {"MaxSize", "StandaloneMsg", "8192"}}; 162 163 private static final int FAKE_SUB_ID = 1; 164 private MockContentResolver mContentResolver; 165 private FakeTelephonyProvider mFakeTelephonyProvider; 166 @Mock 167 Context mContext; 168 169 @Before setUp()170 public void setUp() { 171 MockitoAnnotations.initMocks(this); 172 mFakeTelephonyProvider = new FakeTelephonyProvider(); 173 mContentResolver = new MockContentResolver(); 174 mContentResolver.addProvider(SubscriptionManager.CONTENT_URI.getAuthority(), 175 mFakeTelephonyProvider); 176 when(mContext.getContentResolver()).thenReturn(mContentResolver); 177 createFakeSimInfo(); 178 } 179 180 @After tearDown()181 public void tearDown() { 182 mFakeTelephonyProvider.close(); 183 } 184 185 @Test 186 @SmallTest testLoadAndUpdateConfigForSub()187 public void testLoadAndUpdateConfigForSub() { 188 189 byte[] currentData = RcsConfig.loadRcsConfigForSub(mContext, FAKE_SUB_ID, false); 190 191 RcsConfig.updateConfigForSub(mContext, FAKE_SUB_ID, null, false); 192 byte[] updatedData = RcsConfig.loadRcsConfigForSub(mContext, FAKE_SUB_ID, false); 193 assertNull(updatedData); 194 195 RcsConfig.updateConfigForSub(mContext, FAKE_SUB_ID, TEST_RCS_CONFIG.getBytes(), false); 196 updatedData = RcsConfig.loadRcsConfigForSub(mContext, FAKE_SUB_ID, false); 197 assertTrue(Arrays.equals(updatedData, TEST_RCS_CONFIG.getBytes())); 198 199 RcsConfig.updateConfigForSub(mContext, FAKE_SUB_ID, currentData, false); 200 updatedData = RcsConfig.loadRcsConfigForSub(mContext, FAKE_SUB_ID, false); 201 assertTrue(Arrays.equals(currentData, updatedData)); 202 } 203 204 @Test 205 @SmallTest testCompressAndDecompress()206 public void testCompressAndDecompress() { 207 byte[] compressedData = RcsConfig.compressGzip(TEST_RCS_CONFIG.getBytes()); 208 assertFalse(Arrays.equals(compressedData, TEST_RCS_CONFIG.getBytes())); 209 byte[] decompressedData = RcsConfig.decompressGzip(compressedData); 210 assertTrue(Arrays.equals(decompressedData, TEST_RCS_CONFIG.getBytes())); 211 assertNull(RcsConfig.compressGzip(null)); 212 assertNull(RcsConfig.decompressGzip(null)); 213 byte[] emptyData = new byte[0]; 214 assertEquals(emptyData, RcsConfig.compressGzip(emptyData)); 215 assertEquals(emptyData, RcsConfig.decompressGzip(emptyData)); 216 } 217 218 @Test 219 @SmallTest testParseConfig()220 public void testParseConfig() { 221 RcsConfig config = new RcsConfig(TEST_RCS_CONFIG.getBytes()); 222 223 for (int i = 0; i < TEST_CONFIG_VALUES.length; i++) { 224 assertEquals(config.getString(TEST_CONFIG_VALUES[i][0], null), 225 TEST_CONFIG_VALUES[i][1]); 226 } 227 } 228 229 @Test 230 @SmallTest testGetCharacteristic()231 public void testGetCharacteristic() { 232 RcsConfig config = new RcsConfig(TEST_RCS_CONFIG.getBytes()); 233 234 for (int i = 0; i < VALID_CHARACTERISTICS.length; i++) { 235 assertNotNull(config.getCharacteristic(VALID_CHARACTERISTICS[i])); 236 } 237 238 for (int i = 0; i < INVALID_CHARACTERISTICS.length; i++) { 239 assertNull(config.getCharacteristic(INVALID_CHARACTERISTICS[i])); 240 } 241 } 242 243 @Test 244 @SmallTest testSetAndMoveCharacteristic()245 public void testSetAndMoveCharacteristic() { 246 RcsConfig config = new RcsConfig(TEST_RCS_CONFIG.getBytes()); 247 248 for (String[] sub : SUB_CHARACTERISTICS) { 249 Characteristic[] cl = new Characteristic[sub.length]; 250 int c = 0; 251 for (String cur : sub) { 252 cl[c] = config.getCharacteristic(cur); 253 assertNotNull(cl[c]); 254 config.setCurrentCharacteristic(cl[c]); 255 c++; 256 } 257 258 while (c > 0) { 259 assertEquals(cl[--c], config.getCurrentCharacteristic()); 260 config.moveToParent(); 261 } 262 263 assertEquals(config.getRoot(), config.getCurrentCharacteristic()); 264 } 265 } 266 267 @Test 268 @SmallTest testGetDuplicateParmInDifferentCharacteristics()269 public void testGetDuplicateParmInDifferentCharacteristics() { 270 RcsConfig config = new RcsConfig(TEST_RCS_CONFIG.getBytes()); 271 for (String[] sub : SAME_PARMS_DIFF_CHARS_VALUE_MAP) { 272 config.moveToRoot(); 273 if (!sub[1].isEmpty()) { 274 config.setCurrentCharacteristic(config.getCharacteristic(sub[1])); 275 } 276 277 String value = config.getString(sub[0], ""); 278 279 assertEquals(value, sub[2]); 280 } 281 } 282 283 @Test 284 @SmallTest testIsRcsVolteSingleRegistrationSupported()285 public void testIsRcsVolteSingleRegistrationSupported() { 286 String[] vals = new String[]{"0", "1", "2"}; 287 boolean[] expectedResHome = new boolean[]{false, true, true}; 288 boolean[] expectedResRoaming = new boolean[]{false, true, false}; 289 for (int i = 0; i < vals.length; i++) { 290 String xml = "\t\t\t\t<characteristic type=\"GSMA\">\n" 291 + "\t\t\t\t\t<parm name=\"rcsVolteSingleRegistration\" value=\"" 292 + vals[i] + "\"/>\n" + "\t\t\t\t</characteristic>\n"; 293 RcsConfig config = new RcsConfig(xml.getBytes()); 294 assertEquals(config.isRcsVolteSingleRegistrationSupported(false), expectedResHome[i]); 295 assertEquals(config.isRcsVolteSingleRegistrationSupported(true), 296 expectedResRoaming[i]); 297 } 298 } 299 createFakeSimInfo()300 private void createFakeSimInfo() { 301 ContentValues contentValues = new ContentValues(); 302 final String fakeIccId = "fakeleIccId"; 303 final String fakeCardId = "fakeCardId"; 304 contentValues.put(SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID, FAKE_SUB_ID); 305 contentValues.put(SubscriptionManager.ICC_ID, fakeIccId); 306 contentValues.put(SubscriptionManager.CARD_ID, fakeCardId); 307 mContentResolver.insert(SubscriptionManager.CONTENT_URI, contentValues); 308 } 309 } 310