Home | History | Annotate | Download | only in nfc
      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