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