1 /* 2 * Copyright (C) 2010 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 com.android.internal.nfc; 18 19 import java.io.IOException; 20 21 import android.nfc.ErrorCodes; 22 import android.nfc.ILlcpSocket; 23 import android.os.RemoteException; 24 import android.util.Log; 25 26 /** 27 * LlcpClientSocket represents a LLCP Connection-Oriented client to be used in a 28 * connection-oriented communication 29 */ 30 public class LlcpSocket { 31 32 private static final String TAG = "LlcpSocket"; 33 34 /** 35 * The handle returned by the NFC service and used to identify the LLCP 36 * socket in every call of this class. 37 */ 38 protected int mHandle; 39 40 /** 41 * The entry point for LLCP socket operations. 42 */ 43 protected ILlcpSocket mService; 44 45 static LlcpException convertErrorToLlcpException(int errorCode) { 46 return convertErrorToLlcpException(errorCode, null); 47 } 48 49 static LlcpException convertErrorToLlcpException(int errorCode, 50 String message) { 51 if (message == null) { 52 message = ""; 53 } else { 54 message = " (" + message + ")"; 55 } 56 57 switch (errorCode) { 58 case ErrorCodes.ERROR_SOCKET_CREATION: 59 return new LlcpException( 60 "Error during the creation of an Llcp socket" + message); 61 case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: 62 return new LlcpException("Not enough ressources are available" 63 + message); 64 case ErrorCodes.ERROR_SOCKET_NOT_CONNECTED: 65 return new LlcpException("Socket not connected to an Llcp Service" 66 + message); 67 default: 68 return new LlcpException("Unkown error code " + errorCode + message); 69 } 70 } 71 72 /** 73 * Internal constructor for the LlcpSocket class. 74 * 75 * @param service 76 * The entry point to the Nfc Service for LlcpServiceSocket 77 * class. 78 * @param handle 79 * The handle returned by the NFC service and used to identify 80 * the socket in subsequent calls. 81 * @hide 82 */ 83 public LlcpSocket(ILlcpSocket service, int handle) { 84 this.mService = service; 85 this.mHandle = handle; 86 } 87 88 /** 89 * Connect request to a specific LLCP Service by its SAP. 90 * 91 * @param sap 92 * Service Access Point number of the LLCP Service 93 * @throws IOException 94 * if the LLCP has been lost or deactivated. 95 * @throws LlcpException 96 * if the connection request is rejected by the remote LLCP 97 * Service 98 */ 99 public void connect(int sap) throws IOException, LlcpException { 100 try { 101 int result = mService.connect(mHandle, sap); 102 // Handle potential errors 103 if (ErrorCodes.isError(result)) { 104 if (result == ErrorCodes.ERROR_IO) { 105 throw new IOException(); 106 } else { 107 throw convertErrorToLlcpException(result); 108 } 109 } 110 } catch (RemoteException e) { 111 Log.e(TAG, "RemoteException in accept(): ", e); 112 } 113 } 114 115 /** 116 * Connect request to a specific LLCP Service by its Service Name. 117 * 118 * @param sn 119 * Service Name of the LLCP Service 120 * @throws IOException 121 * if the LLCP has been lost or deactivated. 122 * @throws LlcpException 123 * if the connection request is rejected by the remote LLCP 124 * Service 125 */ 126 public void connect(String sn) throws IOException, LlcpException { 127 try { 128 int result = mService.connectByName(mHandle, sn); 129 // Handle potential errors 130 if (ErrorCodes.isError(result)) { 131 if (result == ErrorCodes.ERROR_IO) { 132 throw new IOException(); 133 } else { 134 throw convertErrorToLlcpException(result); 135 } 136 } 137 } catch (RemoteException e) { 138 Log.e(TAG, "RemoteException in accept(): ", e); 139 } 140 } 141 142 /** 143 * Disconnect request to the connected LLCP socket and close the created 144 * socket. 145 * 146 * @throws IOException 147 * if the LLCP has been lost or deactivated. 148 */ 149 public void close() throws IOException { 150 try { 151 int result = mService.close(mHandle); 152 // Handle potential errors 153 if (ErrorCodes.isError(result)) { 154 throw new IOException(); 155 } 156 } catch (RemoteException e) { 157 Log.e(TAG, "RemoteException in close(): ", e); 158 } 159 } 160 161 /** 162 * Send data to the connected LLCP Socket. 163 * 164 * @throws IOException 165 * if the LLCP has been lost or deactivated. 166 */ 167 public void send(byte[] data) throws IOException { 168 try { 169 int result = mService.send(mHandle, data); 170 // Handle potential errors 171 if (ErrorCodes.isError(result)) { 172 throw new IOException(); 173 } 174 } catch (RemoteException e) { 175 Log.e(TAG, "RemoteException in send(): ", e); 176 } 177 } 178 179 /** 180 * Receive data from the connected LLCP socket 181 * 182 * @param receiveBuffer 183 * a buffer for the received data 184 * @return length length of the data received 185 * @throws IOException 186 * if the LLCP has been lost or deactivated. 187 */ 188 public int receive(byte[] receiveBuffer) throws IOException { 189 int receivedLength = 0; 190 try { 191 receivedLength = mService.receive(mHandle, receiveBuffer); 192 if(receivedLength == 0){ 193 throw new IOException(); 194 } 195 } catch (RemoteException e) { 196 Log.e(TAG, "RemoteException in send(): ", e); 197 } 198 199 return receivedLength; 200 } 201 202 /** 203 * Returns the local Service Access Point number of the socket 204 * 205 * @return localSap 206 */ 207 public int getLocalSap() { 208 try { 209 return mService.getLocalSap(mHandle); 210 } catch (RemoteException e) { 211 Log.e(TAG, "RemoteException in getLocalSap(): ", e); 212 return 0; 213 } 214 } 215 216 /** 217 * Returns the local Maximum Information Unit(MIU) of the socket 218 * 219 * @return miu 220 */ 221 public int getLocalSocketMiu() { 222 try { 223 return mService.getLocalSocketMiu(mHandle); 224 } catch (RemoteException e) { 225 Log.e(TAG, "RemoteException in getLocalSocketMiu(): ", e); 226 return 0; 227 } 228 } 229 230 /** 231 * Returns the local Receive Window(RW) of the socket 232 * 233 * @return rw 234 */ 235 public int getLocalSocketRw() { 236 try { 237 return mService.getLocalSocketRw(mHandle); 238 } catch (RemoteException e) { 239 Log.e(TAG, "RemoteException in getLocalSocketRw(): ", e); 240 return 0; 241 } 242 } 243 244 /** 245 * Returns the remote Maximum Information Unit(MIU) of the socket. 246 * <p> 247 * This method must be called when the socket is in CONNECTED_STATE 248 * 249 * @return remoteMiu 250 * @throws LlcpException 251 * if the LlcpClientSocket is not in a CONNECTED_STATE 252 */ 253 public int getRemoteSocketMiu() throws LlcpException { 254 try { 255 int result = mService.getRemoteSocketMiu(mHandle); 256 if(result != ErrorCodes.ERROR_SOCKET_NOT_CONNECTED){ 257 return result; 258 }else{ 259 throw convertErrorToLlcpException(result); 260 } 261 } catch (RemoteException e) { 262 Log.e(TAG, "RemoteException in getRemoteSocketMiu(): ", e); 263 return 0; 264 } 265 } 266 267 /** 268 * Returns the remote Receive Window(RW) of the connected remote socket. 269 * <p> 270 * This method must be called when the socket is in CONNECTED_STATE 271 * 272 * @return rw 273 * @throws LlcpException 274 * if the LlcpClientSocket is not in a CONNECTED_STATE 275 */ 276 public int getRemoteSocketRw() throws LlcpException { 277 try { 278 int result = mService.getRemoteSocketRw(mHandle); 279 if( result != ErrorCodes.ERROR_SOCKET_NOT_CONNECTED){ 280 return result; 281 }else{ 282 throw convertErrorToLlcpException(result); 283 } 284 } catch (RemoteException e) { 285 Log.e(TAG, "RemoteException in getRemoteSocketRw(): ", e); 286 return 0; 287 } 288 } 289 } 290