1 /* 2 * Copyright (C) 2017 NXP Semiconductors 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.sneptest; 17 18 import android.content.Context; 19 import android.nfc.NdefMessage; 20 import android.util.Log; 21 22 import com.android.nfc.DeviceHost.LlcpSocket; 23 import com.android.nfc.DtaServiceConnector; 24 import com.android.nfc.LlcpException; 25 import com.android.nfc.NfcService; 26 import com.android.nfc.snep.SnepException; 27 import com.android.nfc.snep.SnepMessage; 28 import com.android.nfc.snep.SnepMessenger; 29 30 import java.io.IOException; 31 import java.io.UnsupportedEncodingException; 32 33 public final class DtaSnepClient { 34 private static final String TAG = "DtaSnepClient"; 35 private static final boolean DBG = true; 36 private static final int DEFAULT_ACCEPTABLE_LENGTH = 1024; 37 private static final int DEFAULT_MIU = 128; 38 private static final int DEFAULT_RWSIZE = 1; 39 private static final int DEFAULT_PORT = 63; 40 private static final String SNEP_SERVICE_NAME = "urn:nfc:sn:snep"; 41 private static final String DEFAULT_SERVICE_NAME = SNEP_SERVICE_NAME; 42 private final Object mTransmissionLock = new Object(); 43 44 private int mState = DISCONNECTED; 45 private final int mAcceptableLength; 46 private final int mFragmentLength; 47 private final int mMiu; 48 private final int mPort; 49 private final int mRwSize; 50 private final String mServiceName; 51 public static int mTestCaseId; 52 53 private static final int DISCONNECTED = 0; 54 private static final int CONNECTING = 1; 55 private static final int CONNECTED = 2; 56 57 SnepMessenger mMessenger = null; 58 DtaSnepClient()59 public DtaSnepClient() { 60 mServiceName = DEFAULT_SERVICE_NAME; 61 mPort = DEFAULT_PORT; 62 mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH; 63 mFragmentLength = -1; 64 mMiu = DEFAULT_MIU; 65 mRwSize = DEFAULT_RWSIZE; 66 } 67 DtaSnepClient(String serviceName, int miu, int rwSize, int testCaseId)68 public DtaSnepClient(String serviceName, int miu, int rwSize, int testCaseId) { 69 mServiceName = serviceName; 70 mPort = -1; 71 mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH; 72 mFragmentLength = -1; 73 mMiu = miu; 74 mRwSize = rwSize; 75 mTestCaseId = testCaseId; 76 } 77 DtaClientOperations(Context mContext)78 public void DtaClientOperations(Context mContext) { 79 DtaServiceConnector dtaServiceConnector=new DtaServiceConnector(mContext); 80 dtaServiceConnector.bindService(); 81 if (DBG) Log.d(TAG, "Connecting remote server"); 82 try { 83 connect(); 84 } catch(IOException e) { 85 Log.e(TAG, "Error connecting remote server"); 86 } 87 switch(mTestCaseId) { 88 //TC_C_BIT_BV_01 89 case 1: 90 { 91 try { 92 if (DBG) Log.d(TAG, "PUT Small Ndef Data"); 93 put(SnepMessage.getSmallNdef()); 94 dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString()); 95 } catch (UnsupportedEncodingException e) { 96 e.printStackTrace(); 97 } catch (IOException e) { 98 e.printStackTrace(); 99 } 100 close(); 101 } 102 break; 103 //TC_C_BIT_BI_01_0 104 case 2: 105 { 106 try { 107 if (DBG) Log.d(TAG, "PUT Small Ndef Data"); 108 put(SnepMessage.getSmallNdef()); 109 dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString()); 110 } catch (UnsupportedEncodingException e) { 111 e.printStackTrace(); 112 } catch (IOException e) { 113 e.printStackTrace(); 114 } 115 close(); 116 } 117 break; 118 //TC_C_BIT_BI_01_1 119 case 3: 120 { 121 try { 122 if (DBG) Log.d(TAG, "PUT Small Ndef Data"); 123 put(SnepMessage.getSmallNdef()); 124 dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString()); 125 } catch (UnsupportedEncodingException e) { 126 e.printStackTrace(); 127 } catch (IOException e) { 128 e.printStackTrace(); 129 } 130 close(); 131 } 132 break; 133 //TC_C_PUT_BV_01 134 case 4: 135 { 136 try { 137 if (DBG) Log.d(TAG, "PUT Small Ndef Data"); 138 put(SnepMessage.getSmallNdef()); 139 dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString()); 140 } catch (UnsupportedEncodingException e) { 141 e.printStackTrace(); 142 } catch (IOException e) { 143 e.printStackTrace(); 144 } 145 close(); 146 } 147 break; 148 //TC_C_PUT_BV_02 149 case 5: 150 { 151 try { 152 if (DBG) Log.d(TAG, "PUT Large Ndef Data"); 153 put(SnepMessage.getLargeNdef()); 154 dtaServiceConnector.sendMessage(SnepMessage.getLargeNdef().toString()); 155 } catch (UnsupportedEncodingException e) { 156 e.printStackTrace(); 157 } catch (IOException e) { 158 e.printStackTrace(); 159 } 160 close(); 161 } 162 break; 163 //TC_C_PUT_BI_01 164 case 6: 165 { 166 try { 167 if (DBG) Log.d(TAG, "PUT Large Ndef Data"); 168 put(SnepMessage.getLargeNdef()); 169 dtaServiceConnector.sendMessage(SnepMessage.getLargeNdef().toString()); 170 } catch (UnsupportedEncodingException e) { 171 e.printStackTrace(); 172 } catch (IOException e) { 173 e.printStackTrace(); 174 } 175 close(); 176 } 177 break; 178 //TC_C_GET_BV_01 179 case 7: 180 { 181 try { 182 if (DBG) Log.d(TAG, "GET Ndef Message"); 183 get(SnepMessage.getSmallNdef()); 184 dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString()); 185 } catch (UnsupportedEncodingException e) { 186 e.printStackTrace(); 187 } catch (IOException e) { 188 e.printStackTrace(); 189 } 190 close(); 191 } 192 break; 193 //TC_C_GET_BV_02 194 case 8: 195 { 196 try { 197 if (DBG) Log.d(TAG, "GET Ndef Message"); 198 get(SnepMessage.getSmallNdef()); 199 dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString()); 200 } catch (UnsupportedEncodingException e) { 201 e.printStackTrace(); 202 } catch (IOException e) { 203 e.printStackTrace(); 204 } 205 close(); 206 } 207 break; 208 //TC_C_GET_BV_03 209 case 9: 210 { 211 try { 212 if (DBG) Log.d(TAG, "GET Ndef Message"); 213 get(SnepMessage.getSmallNdef()); 214 dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString()); 215 } catch (UnsupportedEncodingException e) { 216 e.printStackTrace(); 217 } catch (IOException e) { 218 e.printStackTrace(); 219 } 220 close(); 221 } 222 break; 223 default: 224 if (DBG) Log.d(TAG, "Unknown test case"); 225 } 226 } 227 put(NdefMessage msg)228 public void put(NdefMessage msg) throws IOException { 229 SnepMessenger messenger; 230 synchronized (this) { 231 if (mState != CONNECTED) { 232 throw new IOException("Socket not connected."); 233 } 234 messenger = mMessenger; 235 } 236 237 synchronized (mTransmissionLock) { 238 try { 239 messenger.sendMessage(SnepMessage.getPutRequest(msg)); 240 messenger.getMessage(); 241 } catch (SnepException e) { 242 throw new IOException(e); 243 } 244 } 245 } 246 get(NdefMessage msg)247 public SnepMessage get(NdefMessage msg) throws IOException { 248 SnepMessenger messenger; 249 synchronized (this) { 250 if (mState != CONNECTED) { 251 throw new IOException("Socket not connected."); 252 } 253 messenger = mMessenger; 254 } 255 256 synchronized (mTransmissionLock) { 257 try { 258 messenger.sendMessage(SnepMessage.getGetRequest(mAcceptableLength, msg)); 259 return messenger.getMessage(); 260 } catch (SnepException e) { 261 throw new IOException(e); 262 } 263 } 264 } 265 connect()266 public void connect() throws IOException { 267 synchronized (this) { 268 if (mState != DISCONNECTED) { 269 throw new IOException("Socket already in use."); 270 } 271 mState = CONNECTING; 272 } 273 274 LlcpSocket socket = null; 275 SnepMessenger messenger; 276 try { 277 if (DBG) Log.d(TAG, "about to create socket"); 278 // Connect to the snep server on the remote side 279 socket = NfcService.getInstance().createLlcpSocket(0, mMiu, mRwSize, 1024); 280 if (socket == null) { 281 throw new IOException("Could not connect to socket."); 282 } 283 if (mPort == -1) { 284 if (DBG) Log.d(TAG, "about to connect to service " + mServiceName); 285 socket.connectToService(mServiceName); 286 } else { 287 if (DBG) Log.d(TAG, "about to connect to port " + mPort); 288 socket.connectToSap(mPort); 289 } 290 int miu = socket.getRemoteMiu(); 291 int fragmentLength = (mFragmentLength == -1) ? miu : Math.min(miu, mFragmentLength); 292 messenger = new SnepMessenger(true, socket, fragmentLength); 293 } catch (LlcpException e) { 294 synchronized (this) { 295 mState = DISCONNECTED; 296 } 297 throw new IOException("Could not connect to socket"); 298 } catch (IOException e) { 299 if (socket != null) { 300 try { 301 socket.close(); 302 } catch (IOException e2) {} 303 } 304 synchronized (this) { 305 mState = DISCONNECTED; 306 } 307 throw new IOException("Failed to connect to socket"); 308 } 309 310 synchronized (this) { 311 mMessenger = messenger; 312 mState = CONNECTED; 313 } 314 } 315 close()316 public void close() { 317 synchronized (this) { 318 if (mMessenger != null) { 319 try { 320 mMessenger.close(); 321 } catch (IOException e) { 322 // ignore 323 } finally { 324 mMessenger = null; 325 mState = DISCONNECTED; 326 } 327 } 328 } 329 } 330 } 331