1 /* Copyright (c) 2016, The Linux Foundation. All rights reserved.
2  *
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are
5  * met:
6  *     * Redistributions of source code must retain the above copyright
7  *       notice, this list of conditions and the following disclaimer.
8  *     * Redistributions in binary form must reproduce the above
9  *       copyright notice, this list of conditions and the following
10  *       disclaimer in the documentation and/or other materials provided
11  *       with the distribution.
12  *     * Neither the name of The Linux Foundation nor the names of its
13  *       contributors may be used to endorse or promote products derived
14  *       from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 package com.android.internal.telephony.uicc;
31 
32 import static com.android.internal.telephony.uicc.IccRecords.EVENT_APP_DETECTED;
33 import static com.android.internal.telephony.uicc.IccRecords.EVENT_APP_READY;
34 
35 import static org.junit.Assert.assertEquals;
36 import static org.junit.Assert.assertFalse;
37 import static org.junit.Assert.assertNull;
38 import static org.junit.Assert.assertTrue;
39 import static org.mockito.Mockito.eq;
40 import static org.mockito.Mockito.isNull;
41 import static org.mockito.Mockito.verify;
42 
43 import android.os.AsyncResult;
44 import android.os.HandlerThread;
45 import android.os.Message;
46 import android.os.SystemClock;
47 import android.util.Log;
48 import android.util.Pair;
49 
50 import com.android.internal.telephony.TelephonyTest;
51 import com.android.internal.telephony.uicc.IccRecords.OperatorPlmnInfo;
52 import com.android.internal.telephony.uicc.IccRecords.PlmnNetworkName;
53 
54 import org.junit.After;
55 import org.junit.Before;
56 import org.junit.Test;
57 
58 import java.util.ArrayList;
59 import java.util.List;
60 
61 public class IccRecordsTest extends TelephonyTest {
62 
63     private IccRecords mIccRecords;
64 
65     private class IccRecordsTestHandler extends HandlerThread {
IccRecordsTestHandler(String name)66         private IccRecordsTestHandler(String name) {
67             super(name);
68         }
69 
70         @Override
onLooperPrepared()71         public void onLooperPrepared() {
72             mIccRecords = new SIMRecords(mUiccCardApplication3gpp, mContext, mSimulatedCommands);
73             setReady(true);
74         }
75     }
76 
77     @Before
setUp()78     public void setUp() throws Exception {
79         super.setUp(this.getClass().getSimpleName());
80         new IccRecordsTestHandler(TAG).start();
81         waitUntilReady();
82         verify(mUiccCardApplication3gpp).registerForReady(
83                 mIccRecords, EVENT_APP_READY, null);
84         verify(mUiccCardApplication3gpp).registerForDetected(
85                 mIccRecords, EVENT_APP_DETECTED, null);
86     }
87 
88     @After
tearDown()89     public void tearDown() throws Exception {
90         mIccRecords = null;
91         super.tearDown();
92     }
93 
94     @Test
testDisposeCallsUnregisterForIccRefresh()95     public void testDisposeCallsUnregisterForIccRefresh() {
96         // verify called below when IccRecords object is created
97         verify(mSimulatedCommandsVerifier).registerForIccRefresh(eq(mIccRecords),
98                     eq(IccRecords.EVENT_REFRESH), isNull());
99         mIccRecords.dispose();
100         // verify called within dispose
101         verify(mSimulatedCommandsVerifier).unregisterForIccRefresh(eq(mIccRecords));
102 
103     }
104 
105     @Test
testSetImsiInvalid()106     public void testSetImsiInvalid() {
107         mIccRecords.setImsi("0123456789FFFFFF");
108         assertEquals(mIccRecords.getIMSI(), "0123456789");
109         mIccRecords.setImsi("0123456789ffffff");
110         assertEquals(mIccRecords.getIMSI(), "0123456789");
111         mIccRecords.setImsi("ffffff");
112         assertEquals(mIccRecords.getIMSI(), null);
113         mIccRecords.setImsi("12F34F567890");
114         assertEquals(mIccRecords.getIMSI(), null);
115         mIccRecords.setImsi("123456ABCDEF");
116         assertEquals(mIccRecords.getIMSI(), null);
117     }
118 
119     @Test
testPendingTansaction()120     public void testPendingTansaction() {
121         Message msg = Message.obtain();
122         Object obj = new Object();
123         int key = mIccRecords.storePendingTransaction(msg, obj);
124         Pair<Message, Object> pair = mIccRecords.retrievePendingTransaction(key);
125         assertEquals(msg, pair.first);
126         assertEquals(obj, pair.second);
127         pair = mIccRecords.retrievePendingTransaction(key);
128         assertNull(pair);
129     }
130 
131     @Test
testGetSmsCapacityOnIcc()132     public void testGetSmsCapacityOnIcc() {
133         // set the number of records to 500
134         int[] records = new int[3];
135         records[2] = 500;
136         Message fetchCapacityDone = mIccRecords.obtainMessage(
137                 IccRecords.EVENT_GET_SMS_RECORD_SIZE_DONE);
138         AsyncResult.forMessage(fetchCapacityDone, records, null);
139         fetchCapacityDone.sendToTarget();
140 
141         // verify whether the count is 500
142         waitForLastHandlerAction(mIccRecords);
143         assertEquals(mIccRecords.getSmsCapacityOnIcc(), 500);
144     }
145 
146     @Test
testGetIccSimChallengeResponseNull()147     public void testGetIccSimChallengeResponseNull() {
148         long startTime;
149         long timeSpent;
150 
151         // EAP-SIM rand is 16 bytes.
152         String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM=";
153 
154         // Test for null result
155         mSimulatedCommands.setAuthenticationMode(mSimulatedCommands.ICC_AUTHENTICATION_MODE_NULL);
156 
157         startTime = SystemClock.elapsedRealtime();
158         assertNull("getIccAuthentication should return null for empty data.",
159                 mIccRecords.getIccSimChallengeResponse(UiccCardApplication.AUTH_CONTEXT_EAP_AKA,
160                       base64Challenge));
161         timeSpent = SystemClock.elapsedRealtime() - startTime;
162         Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
163         assertTrue("getIccAuthentication should not timeout",
164                 timeSpent < mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS);
165     }
166 
167     @Test
testGetIccSimChallengeResponseTimeout()168     public void testGetIccSimChallengeResponseTimeout() {
169         long startTime;
170         long timeSpent;
171 
172         // EAP-SIM rand is 16 bytes.
173         String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM=";
174 
175         mSimulatedCommands.setAuthenticationMode(
176                 mSimulatedCommands.ICC_AUTHENTICATION_MODE_TIMEOUT);
177         startTime = SystemClock.elapsedRealtime();
178         assertNull("getIccAuthentication should return null for empty data.",
179                 mIccRecords.getIccSimChallengeResponse(UiccCardApplication.AUTH_CONTEXT_EAP_AKA,
180                       base64Challenge));
181         timeSpent = SystemClock.elapsedRealtime() - startTime;
182         Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
183         assertTrue("getIccAuthentication should timeout",
184                 timeSpent >= mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS);
185     }
186 
187     @Test
testAppStateChange()188     public void testAppStateChange() {
189         assertFalse(mIccRecords.isLoaded());
190 
191         mIccRecords.obtainMessage(EVENT_APP_READY).sendToTarget();
192         waitForLastHandlerAction(mIccRecords);
193         assertTrue(mIccRecords.isLoaded());
194 
195         mIccRecords.obtainMessage(EVENT_APP_DETECTED).sendToTarget();
196         waitForLastHandlerAction(mIccRecords);
197         assertFalse(mIccRecords.isLoaded());
198 
199         mIccRecords.obtainMessage(EVENT_APP_READY).sendToTarget();
200         waitForLastHandlerAction(mIccRecords);
201         assertTrue(mIccRecords.isLoaded());
202     }
203 
204     @Test
testGetIccSimChallengeResponseDefault()205     public void testGetIccSimChallengeResponseDefault() {
206         long startTime;
207         long timeSpent;
208 
209         // EAP-SIM rand is 16 bytes.
210         String base64Challenge = "ECcTqwuo6OfY8ddFRboD9WM=";
211         String base64Challenge2 = "EMNxjsFrPCpm+KcgCmQGnwQ=";
212 
213         // Test for default setup
214         mSimulatedCommands.setAuthenticationMode(
215                 mSimulatedCommands.ICC_AUTHENTICATION_MODE_DEFAULT);
216 
217         // Test for null input
218         startTime = SystemClock.elapsedRealtime();
219         assertNull("getIccAuthentication should return null for empty data.",
220                 mIccRecords.getIccSimChallengeResponse(
221                         UiccCardApplication.AUTH_CONTEXT_EAP_AKA, ""));
222         timeSpent = SystemClock.elapsedRealtime() - startTime;
223         Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
224         assertTrue("getIccAuthentication should not timeout",
225                 timeSpent < mSimulatedCommands.ICC_SIM_CHALLENGE_TIMEOUT_MILLIS);
226 
227         // EAP-SIM
228         startTime = SystemClock.elapsedRealtime();
229         String response = mIccRecords.getIccSimChallengeResponse(
230                 UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge);
231         timeSpent = SystemClock.elapsedRealtime() - startTime;
232         Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
233         Log.d("IccRecordsTest", "Result of getIccSimChallengeResponse is " + response);
234         assertTrue("Response to EAP-SIM Challenge must not be Null.", response != null);
235 
236         startTime = SystemClock.elapsedRealtime();
237         String response1 = mIccRecords.getIccSimChallengeResponse(
238                 UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge);
239         timeSpent = SystemClock.elapsedRealtime() - startTime;
240         Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
241         Log.d("IccRecordsTest", "Result of getIccSimChallengeResponse is " + response1);
242         assertTrue("Response to EAP-SIM Challenge must be consistent.",
243                 response.equals(response1));
244 
245         startTime = SystemClock.elapsedRealtime();
246         String response2 = mIccRecords.getIccSimChallengeResponse(
247                 UiccCardApplication.AUTH_CONTEXT_EAP_SIM, base64Challenge2);
248         timeSpent = SystemClock.elapsedRealtime() - startTime;
249         Log.d("IccRecordsTest", "Time (ms) for getIccSimChallengeResponse is " + timeSpent);
250         assertTrue("Two responses must be different.", !response.equals(response2));
251     }
252 
253     @Test
testOperatorPlmnInfo()254     public void testOperatorPlmnInfo() {
255         String plmn = "123456";
256         int lacTacStart = 0x0000;
257         int lacTacEnd = 0xFFFE;
258         int pnnIndex = 2;
259 
260         OperatorPlmnInfo opi = new OperatorPlmnInfo(plmn, lacTacStart, lacTacEnd, pnnIndex);
261         assertEquals(opi.getPnnIdx(plmn, lacTacStart), pnnIndex - 1);
262         assertEquals(opi.getPnnIdx(plmn, lacTacEnd), pnnIndex - 1);
263         assertEquals(opi.getPnnIdx(plmn, 0xFFFF), pnnIndex - 1);
264         assertEquals(opi.getPnnIdx("654321", 0xFFFF), -1);
265         assertEquals(opi.getPnnIdx("12345", 0xFFFF), -1);
266 
267         lacTacStart = 0x0001;
268         lacTacEnd = 0x1FFF;
269         opi = new OperatorPlmnInfo(plmn, lacTacStart, lacTacEnd, pnnIndex);
270         assertEquals(opi.getPnnIdx(plmn, 2), pnnIndex - 1);
271         assertEquals(opi.getPnnIdx(plmn, 0x2FFF), -1);
272         assertEquals(opi.getPnnIdx(plmn, 0xFFFF), -1);
273 
274         plmn = "123DDD";
275         opi = new OperatorPlmnInfo(plmn, lacTacStart, lacTacEnd, pnnIndex);
276         assertEquals(opi.getPnnIdx("123123", lacTacStart), pnnIndex - 1);
277         assertEquals(opi.getPnnIdx("12345", lacTacStart), -1);
278     }
279 
280     @Test
testGetNetworkNameForPlmn()281     public void testGetNetworkNameForPlmn() {
282         // Set up PNN
283         String fullName1 = "Name full 1";
284         String shortName1 = "Name short 1";
285         String fullName2 = "Name full 2";
286         String shortName2 = "Name short 2";
287         List<PlmnNetworkName> pnns = new ArrayList<PlmnNetworkName>();
288         pnns.add(new PlmnNetworkName(fullName1, shortName1));
289         pnns.add(new PlmnNetworkName(fullName2, shortName2));
290         pnns.add(new PlmnNetworkName(null, shortName2));
291         PlmnNetworkName[] pnnsArray = pnns.toArray(new PlmnNetworkName[0]);
292 
293         // Set up OPL
294         String plmn1 = "345678";
295         String plmn2 = "456789";
296         String plmn3 = "567890";
297         int lacTacStart = 0x0000;
298         int lacTacEnd = 0xFFFE;
299         int pnnIndex = 1;
300         List<OperatorPlmnInfo> opl = new ArrayList<OperatorPlmnInfo>();
301         opl.add(new OperatorPlmnInfo(plmn1, lacTacStart, lacTacEnd, pnnIndex));
302         opl.add(new OperatorPlmnInfo(plmn2, lacTacStart, lacTacEnd, pnnIndex + 1));
303         opl.add(new OperatorPlmnInfo(plmn3, lacTacStart, lacTacEnd, pnnIndex + 2));
304         OperatorPlmnInfo[] oplArray = opl.toArray(new OperatorPlmnInfo[0]);
305 
306         // Test
307         assertNull(IccRecords.getNetworkNameForPlmnFromPnnOpl(pnnsArray, oplArray, null, 0));
308         assertEquals(fullName1, IccRecords.getNetworkNameForPlmnFromPnnOpl(pnnsArray, oplArray,
309                 plmn1, 0));
310         assertEquals(fullName2, IccRecords.getNetworkNameForPlmnFromPnnOpl(pnnsArray, oplArray,
311                 plmn2, 0));
312         assertEquals(shortName2, IccRecords.getNetworkNameForPlmnFromPnnOpl(pnnsArray, oplArray,
313                 plmn3, 0));
314     }
315 
316     @Test
testGetNetworkNameForPlmnFromPnnOpl()317     public void testGetNetworkNameForPlmnFromPnnOpl() {
318         // Set up PNN
319         String fullName1 = "Name full 1";
320         String shortName1 = "Name short 1";
321         String fullName2 = "Name full 2";
322         String shortName2 = "Name short 2";
323         List<PlmnNetworkName> pnns = new ArrayList<PlmnNetworkName>();
324         pnns.add(new PlmnNetworkName(fullName1, shortName1));
325         pnns.add(new PlmnNetworkName(fullName2, shortName2));
326         pnns.add(new PlmnNetworkName(null, shortName2));
327         PlmnNetworkName[] pnnsArray = pnns.toArray(new PlmnNetworkName[0]);
328 
329         // Set up OPL
330         String plmn1 = "345678";
331         String plmn2 = "456789";
332         String plmn3 = "567890";
333         int lacTacStart = 0x0000;
334         int lacTacEnd = 0xFFFE;
335         int pnnIndex = 1;
336         List<OperatorPlmnInfo> opl = new ArrayList<OperatorPlmnInfo>();
337         opl.add(new OperatorPlmnInfo(plmn1, lacTacStart, lacTacEnd, pnnIndex));
338         opl.add(new OperatorPlmnInfo(plmn2, lacTacStart, lacTacEnd, pnnIndex + 1));
339         opl.add(new OperatorPlmnInfo(plmn3, lacTacStart, lacTacEnd, pnnIndex + 2));
340         OperatorPlmnInfo[] oplArray = opl.toArray(new OperatorPlmnInfo[0]);
341 
342         // Test
343         assertNull(IccRecords.getNetworkNameForPlmnFromPnnOpl(pnnsArray, oplArray, null, 0));
344         assertEquals(fullName1, IccRecords.getNetworkNameForPlmnFromPnnOpl(pnnsArray, oplArray,
345                 plmn1, 0));
346         assertEquals(fullName2, IccRecords.getNetworkNameForPlmnFromPnnOpl(pnnsArray, oplArray,
347                 plmn2, 0));
348         assertEquals(shortName2, IccRecords.getNetworkNameForPlmnFromPnnOpl(pnnsArray, oplArray,
349                 plmn3, 0));
350     }
351 }
352