• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 package com.android.nfc;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 
20 import androidx.test.ext.junit.runners.AndroidJUnit4;
21 
22 import org.junit.After;
23 import org.junit.Before;
24 import org.junit.Test;
25 import org.junit.runner.RunWith;
26 
27 @RunWith(AndroidJUnit4.class)
28 public final class NfcRoutingTableParseTest {
29     private static final String TAG = NfcRoutingTableParseTest.class.getSimpleName();
30     private RoutingTableParser mRoutingTableParser;
31 
32     // NFCEE-ID
33     static final byte EE_ID_HOST = (byte) 0x00;
34     static final byte EE_ID_UICC = (byte) 0x81;
35     static final byte EE_ID_ESE = (byte) 0x86;
36 
37     // Power State Mask
38     static final byte APPLY_ALL = (byte) 0x3F;
39     static final byte SWITCH_ON_SUB_3 = (byte) 0x20;
40     static final byte SWITCH_ON_SUB_2 = (byte) 0x10;
41     static final byte SWITCH_ON_SUB_1 = (byte) 0x08;
42     static final byte BATTERY_OFF = (byte) 0x04;
43     static final byte SWITCH_OFF = (byte) 0x02;
44     static final byte SWITCH_ON = (byte) 0x01;
45 
46     @Before
setUp()47     public void setUp() {
48         mRoutingTableParser = new RoutingTableParser();
49     }
50 
51     @After
tearDown()52     public void tearDown() throws Exception {
53     }
54 
55     @Test
testParseValidTechnologyEntry()56     public void testParseValidTechnologyEntry() {
57         /**
58          * set qualifier = 0x00 to indicates the routing is allowed for the power modes
59          * where it is not supported
60          */
61         byte qualifier = (byte) 0x00;
62         byte type = RoutingTableParser.TYPE_TECHNOLOGY;
63         byte eeId = EE_ID_HOST;
64         byte pwrState = (byte) (SWITCH_ON_SUB_3 | SWITCH_ON_SUB_2 | SWITCH_ON_SUB_1 | SWITCH_ON);
65         byte[] entry = hexStrToByteArray("01");
66         byte[] rt = generateRoutingEntry(qualifier, type, eeId, pwrState, entry);
67         mRoutingTableParser.parse(rt);
68 
69         int ret = mRoutingTableParser.getCommitStatus(type, entry);
70 
71         assertThat(ret).isEqualTo(mRoutingTableParser.STATS_HOST_OK);
72     }
73 
74     @Test
testParseInvalidTechnologyEntry()75     public void testParseInvalidTechnologyEntry() {
76         /**
77          * set qualifier = 0x00 to indicates the routing is allowed for the power modes
78          * where it is not supported
79          */
80         byte qualifier = (byte) 0x00;
81         byte type = RoutingTableParser.TYPE_TECHNOLOGY;
82         byte eeId = EE_ID_HOST;
83         byte pwrState = (byte) (SWITCH_ON_SUB_3 | SWITCH_ON_SUB_2 | SWITCH_ON_SUB_1 | SWITCH_ON);
84         byte[] entry = hexStrToByteArray("0001");
85         byte[] rt = generateRoutingEntry(qualifier, type, eeId, pwrState, entry);
86         mRoutingTableParser.parse(rt);
87 
88         int ret = mRoutingTableParser.getCommitStatus(type, entry);
89 
90         assertThat(ret).isEqualTo(mRoutingTableParser.STATS_NOT_FOUND);
91     }
92 
93     @Test
testParseValidProtocolEntry()94     public void testParseValidProtocolEntry() {
95         /**
96          * set qualifier = 0x00 to indicates the routing is allowed for the power modes
97          * where it is not supported
98          */
99         byte qualifier = (byte) 0x00;
100         byte type = RoutingTableParser.TYPE_PROTOCOL;
101         byte eeId = EE_ID_HOST;
102         byte pwrState = SWITCH_ON;
103         byte[] entry = hexStrToByteArray("04");
104         byte[] rt = generateRoutingEntry(qualifier, type, eeId, pwrState, entry);
105         mRoutingTableParser.parse(rt);
106 
107         int ret = mRoutingTableParser.getCommitStatus(type, entry);
108 
109         assertThat(ret).isEqualTo(mRoutingTableParser.STATS_HOST_OK);
110     }
111 
112     @Test
testParseInvalidProtocolEntry()113     public void testParseInvalidProtocolEntry() {
114         /**
115          * set qualifier = 0x00 to indicates the routing is allowed for the power modes
116          * where it is not supported
117          */
118         byte qualifier = (byte) 0x00;
119         byte type = RoutingTableParser.TYPE_PROTOCOL;
120         byte eeId = EE_ID_HOST;
121         byte pwrState = SWITCH_ON;
122         byte[] entry = hexStrToByteArray("0405");
123         byte[] rt = generateRoutingEntry(qualifier, type, eeId, pwrState, entry);
124         mRoutingTableParser.parse(rt);
125 
126         int ret = mRoutingTableParser.getCommitStatus(type, entry);
127 
128         assertThat(ret).isEqualTo(mRoutingTableParser.STATS_NOT_FOUND);
129     }
130 
131     @Test
testParseValidAidEntry()132     public void testParseValidAidEntry() {
133         /**
134          * set qualifier = 0x40 to indicates the routing is blocked for the power modes
135          * where it is not supported
136          */
137         byte qualifier = (byte) 0x40;
138         byte type = RoutingTableParser.TYPE_AID;
139         byte eeId = EE_ID_UICC;
140         byte pwrState = (byte) (APPLY_ALL ^ BATTERY_OFF);
141         byte[] entry = hexStrToByteArray("6E6663746573743031");
142         byte[] rt = generateRoutingEntry(qualifier, type, eeId, pwrState, entry);
143         mRoutingTableParser.parse(rt);
144 
145         int ret = mRoutingTableParser.getCommitStatus(type, entry);
146 
147         assertThat(ret).isEqualTo(mRoutingTableParser.STATS_OFFHOST_OK);
148     }
149 
150     @Test
testParseInvalidAidEntry()151     public void testParseInvalidAidEntry() {
152         /**
153          * set qualifier = 0x40 to indicates the routing is blocked for the power modes
154          * where it is not supported
155          */
156         byte qualifier = (byte) 0x40;
157         byte type = RoutingTableParser.TYPE_AID;
158         byte eeId = EE_ID_UICC;
159         byte pwrState = (byte) (APPLY_ALL ^ BATTERY_OFF);
160         byte[] entry = hexStrToByteArray("6E66637465737430316E6663746573743031");
161         byte[] rt = generateRoutingEntry(qualifier, type, eeId, pwrState, entry);
162         mRoutingTableParser.parse(rt);
163 
164         int ret = mRoutingTableParser.getCommitStatus(type, entry);
165 
166         assertThat(ret).isEqualTo(mRoutingTableParser.STATS_NOT_FOUND);
167     }
168 
169     @Test
testParseValidSystemCodeEntry()170     public void testParseValidSystemCodeEntry() {
171         /**
172          * set qualifier = 0x40 to indicates the routing is blocked for the power modes
173          * where it is not supported
174          */
175         byte qualifier = (byte) 0x40;
176         byte type = RoutingTableParser.TYPE_SYSTEMCODE;
177         byte eeId = EE_ID_ESE;
178         byte pwrState = (byte) (APPLY_ALL ^ BATTERY_OFF);
179         byte[] entry = hexStrToByteArray("FEFE");
180         byte[] rt = generateRoutingEntry(qualifier, type, eeId, pwrState, entry);
181         mRoutingTableParser.parse(rt);
182 
183         int ret = mRoutingTableParser.getCommitStatus(type, entry);
184 
185         assertThat(ret).isEqualTo(mRoutingTableParser.STATS_OFFHOST_OK);
186     }
187 
188     @Test
testParseSeveralValidSystemCodeEntry()189     public void testParseSeveralValidSystemCodeEntry() {
190         /**
191          * set qualifier = 0x40 to indicates the routing is blocked for the power modes
192          * where it is not supported
193          */
194         byte qualifier = (byte) 0x40;
195         byte type = RoutingTableParser.TYPE_SYSTEMCODE;
196         byte eeId = EE_ID_ESE;
197         byte pwrState = (byte) (APPLY_ALL ^ BATTERY_OFF);
198         byte[] entry1 = hexStrToByteArray("FEFE");
199         byte[] entry2 = hexStrToByteArray("EEEE");
200         byte[] entryAll = hexStrToByteArray("FEFEEEEE");
201         byte[] rt = generateRoutingEntry(qualifier, type, eeId, pwrState, entryAll);
202         mRoutingTableParser.parse(rt);
203 
204         int ret1 = mRoutingTableParser.getCommitStatus(type, entry1);
205         int ret2 = mRoutingTableParser.getCommitStatus(type, entry2);
206 
207         assertThat(ret1).isEqualTo(mRoutingTableParser.STATS_OFFHOST_OK);
208         assertThat(ret2).isEqualTo(mRoutingTableParser.STATS_OFFHOST_OK);
209     }
210 
211     @Test
testParseInvalidSystemCodeEntry()212     public void testParseInvalidSystemCodeEntry() {
213         /**
214          * set qualifier = 0x40 to indicates the routing is blocked for the power modes
215          * where it is not supported
216          */
217         byte qualifier = (byte) 0x40;
218         byte type = RoutingTableParser.TYPE_SYSTEMCODE;
219         byte eeId = EE_ID_ESE;
220         byte pwrState = (byte) (APPLY_ALL ^ BATTERY_OFF);
221         byte[] entry = hexStrToByteArray("FEFEFE");
222         byte[] rt = generateRoutingEntry(qualifier, type, eeId, pwrState, entry);
223         mRoutingTableParser.parse(rt);
224 
225         int ret = mRoutingTableParser.getCommitStatus(type, entry);
226 
227         assertThat(ret).isEqualTo(mRoutingTableParser.STATS_NOT_FOUND);
228     }
229 
generateRoutingEntry(byte qualifier, byte type, byte eeId, byte pwrState, byte[] entry)230     private byte[] generateRoutingEntry(byte qualifier, byte type, byte eeId, byte pwrState,
231             byte[] entry) {
232         int length = 2 + entry.length;
233         byte[] rt = new byte[length + 2];
234         rt[0] = (byte) (qualifier | type);
235         rt[1] = (byte) length;
236         rt[2] = eeId;
237         rt[3] = pwrState;
238 
239         for (int i = 0; i < entry.length; i++) {
240             rt[i + 4] = entry[i];
241         }
242 
243         return rt;
244     }
245 
hexStrToByteArray(String hexStr)246     private byte[] hexStrToByteArray(String hexStr) {
247         if (hexStr.length() % 2 != 0) {
248             return new byte[0];
249         }
250 
251         char[] hex = hexStr.toCharArray();
252         int length = hexStr.length() / 2;
253         byte[] byteArr = new byte[length];
254         for (int i = 0; i < length; i++) {
255             int high = Character.digit(hex[i * 2], 16);
256             int low = Character.digit(hex[i * 2 + 1], 16);
257             int value = (high << 4) | low;
258 
259             if (value > 127) {
260                 value -= 256;
261             }
262             byteArr [i] = (byte) value;
263         }
264 
265         return byteArr;
266     }
267 }
268