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