diff --git a/Android.mk b/Android.mk index 9492167627689..570fbf8dd1c05 100644 --- a/Android.mk +++ b/Android.mk @@ -161,6 +161,14 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/view/IInputMethodManager.aidl \ core/java/com/android/internal/view/IInputMethodSession.aidl \ core/java/com/android/internal/widget/IRemoteViewsFactory.aidl \ + core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl \ + core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl \ + core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl \ + core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl \ + core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl \ + core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl \ + core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl \ + core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl \ location/java/android/location/ICountryDetector.aidl \ location/java/android/location/ICountryListener.aidl \ location/java/android/location/IGeocodeProvider.aidl \ diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 3174f55530090..918ecf1d69517 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -103,6 +103,8 @@ import android.view.inputmethod.InputMethodManager; import android.accounts.AccountManager; import android.accounts.IAccountManager; import android.app.admin.DevicePolicyManager; +import com.trustedlogic.trustednfc.android.NfcManager; +import com.trustedlogic.trustednfc.android.INfcManager; import com.android.internal.os.IDropBoxManagerService; @@ -173,6 +175,7 @@ class ContextImpl extends Context { private static WifiManager sWifiManager; private static LocationManager sLocationManager; private static CountryDetector sCountryDetector; + private static NfcManager sNfcManager; private static final HashMap sSharedPrefs = new HashMap(); @@ -968,6 +971,8 @@ class ContextImpl extends Context { return getClipboardManager(); } else if (WALLPAPER_SERVICE.equals(name)) { return getWallpaperManager(); + } else if (NFC_SERVICE.equals(name)) { + return getNfcManager(); } else if (DROPBOX_SERVICE.equals(name)) { return getDropBoxManager(); } else if (DEVICE_POLICY_SERVICE.equals(name)) { @@ -1219,6 +1224,21 @@ class ContextImpl extends Context { return mDownloadManager; } + private NfcManager getNfcManager() + { + synchronized (sSync) { + if (sNfcManager == null) { + IBinder b = ServiceManager.getService(NFC_SERVICE); + if (b == null) { + return null; + } + INfcManager service = INfcManager.Stub.asInterface(b); + sNfcManager = new NfcManager(service, mMainThread.getHandler()); + } + } + return sNfcManager; + } + @Override public int checkPermission(String permission, int pid, int uid) { if (permission == null) { diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 3a56afb646317..9c8d69807c60b 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1591,6 +1591,16 @@ public abstract class Context { /** @hide */ public static final String SIP_SERVICE = "sip"; + /** + * Use with {@link #getSystemService} to retrieve an + * {@link com.trustedlogic.trustednfc.android.INfcManager.INfcManager} for + * accessing NFC methods. + * + * @see #getSystemService + * @hide + */ + public static final String NFC_SERVICE = "nfc"; + /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index d8fb658c7bc0b..cf95872a72fa9 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1641,6 +1641,86 @@ public final class Settings { */ public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse"; + /** + * Whether nfc is enabled/disabled + * 0=disabled. 1=enabled. + * @hide + */ + public static final String NFC_ON = "nfc_on"; + + /** + * Whether nfc secure element is enabled/disabled + * 0=disabled. 1=enabled. + * @hide + */ + public static final String NFC_SECURE_ELEMENT_ON = "nfc_secure_element_on"; + + /** + * Whether nfc secure element is enabled/disabled + * 0=disabled. 1=enabled. + * @hide + */ + public static final String NFC_SECURE_ELEMENT_ID = "nfc_secure_element_id"; + + /** + * LLCP LTO value + * @hide + */ + public static final String NFC_LLCP_LTO = "nfc_llcp_lto"; + + /** + * LLCP MIU value + * @hide + */ + public static final String NFC_LLCP_MIU = "nfc_llcp_miu"; + + /** + * LLCP WKS value + * @hide + */ + public static final String NFC_LLCP_WKS = "nfc_llcp_wks"; + + /** + * LLCP OPT value + * @hide + */ + public static final String NFC_LLCP_OPT = "nfc_llcp_opt"; + + /** + * NFC Discovery Reader A + * 0=disabled. 1=enabled. + * @hide + */ + public static final String NFC_DISCOVERY_A = "nfc_discovery_a"; + + /** + * NFC Discovery Reader B + * 0=disabled. 1=enabled. + * @hide + */ + public static final String NFC_DISCOVERY_B = "nfc_discovery_b"; + + /** + * NFC Discovery Reader Felica + * 0=disabled. 1=enabled. + * @hide + */ + public static final String NFC_DISCOVERY_F = "nfc_discovery_felica"; + + /** + * NFC Discovery Reader 15693 + * 0=disabled. 1=enabled. + * @hide + */ + public static final String NFC_DISCOVERY_15693 = "nfc_discovery_15693"; + + /** + * NFC Discovery NFCIP + * 0=disabled. 1=enabled. + * @hide + */ + public static final String NFC_DISCOVERY_NFCIP = "nfc_discovery_nfcip"; + /** * Show pointer location on screen? * 0 = no @@ -1814,7 +1894,19 @@ public final class Settings { NOTIFICATION_LIGHT_PULSE, USE_PTP_INTERFACE, SIP_CALL_OPTIONS, - SIP_RECEIVE_CALLS + SIP_RECEIVE_CALLS, + NFC_ON, + NFC_SECURE_ELEMENT_ON, + NFC_SECURE_ELEMENT_ID, + NFC_LLCP_LTO, + NFC_LLCP_MIU, + NFC_LLCP_WKS, + NFC_LLCP_OPT, + NFC_DISCOVERY_A, + NFC_DISCOVERY_B, + NFC_DISCOVERY_F, + NFC_DISCOVERY_15693, + NFC_DISCOVERY_NFCIP, }; // Settings moved to Settings.Secure diff --git a/core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl b/core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl new file mode 100644 index 0000000000000..35746ad3e1e6b --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android; + +import com.trustedlogic.trustednfc.android.LlcpPacket; + +/** + * TODO + * + * {@hide} + */ +interface ILlcpConnectionlessSocket +{ + + void close(int nativeHandle); + int getSap(int nativeHandle); + LlcpPacket receiveFrom(int nativeHandle); + int sendTo(int nativeHandle, in LlcpPacket packet); + +} \ No newline at end of file diff --git a/core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl b/core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl new file mode 100644 index 0000000000000..5eb1f3cc66942 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android; + +/** + * TODO + * + * {@hide} + */ +interface ILlcpServiceSocket +{ + + int accept(int nativeHandle); + void close(int nativeHandle); + int getAcceptTimeout(int nativeHandle); + void setAcceptTimeout(int nativeHandle, int timeout); + +} \ No newline at end of file diff --git a/core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl b/core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl new file mode 100644 index 0000000000000..e9169d826518b --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android; + +/** + * TODO + * + * {@hide} + */ +interface ILlcpSocket +{ + + int close(int nativeHandle); + int connect(int nativeHandle, int sap); + int connectByName(int nativeHandle, String sn); + int getConnectTimeout(int nativeHandle); + int getLocalSap(int nativeHandle); + int getLocalSocketMiu(int nativeHandle); + int getLocalSocketRw(int nativeHandle); + int getRemoteSocketMiu(int nativeHandle); + int getRemoteSocketRw(int nativeHandle); + int receive(int nativeHandle, out byte[] receiveBuffer); + int send(int nativeHandle, in byte[] data); + void setConnectTimeout(int nativeHandle, int timeout); + +} + diff --git a/core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl b/core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl new file mode 100644 index 0000000000000..1f8d1a41df3c5 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android; + +import com.trustedlogic.trustednfc.android.NdefMessage; + +/** + * TODO + * + * {@hide} + */ +interface INdefTag +{ + + NdefMessage read(int nativeHandle); + boolean write(int nativeHandle, in NdefMessage msg); + +} \ No newline at end of file diff --git a/core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl b/core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl new file mode 100644 index 0000000000000..ce36ab297154f --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android; + +import com.trustedlogic.trustednfc.android.ILlcpSocket; +import com.trustedlogic.trustednfc.android.ILlcpServiceSocket; +import com.trustedlogic.trustednfc.android.ILlcpConnectionlessSocket; +import com.trustedlogic.trustednfc.android.INfcTag; +import com.trustedlogic.trustednfc.android.IP2pTarget; +import com.trustedlogic.trustednfc.android.IP2pInitiator; + + +/** + * Interface that allows controlling NFC activity. + * + * {@hide} + */ +interface INfcManager +{ + + ILlcpSocket getLlcpInterface(); + ILlcpConnectionlessSocket getLlcpConnectionlessInterface(); + ILlcpServiceSocket getLlcpServiceInterface(); + INfcTag getNfcTagInterface(); + IP2pTarget getP2pTargetInterface(); + IP2pInitiator getP2pInitiatorInterface(); + + void cancel(); + int createLlcpConnectionlessSocket(int sap); + int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength); + int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength); + int deselectSecureElement(); + boolean disable(); + boolean enable(); + int getOpenTimeout(); + String getProperties(String param); + int[] getSecureElementList(); + int getSelectedSecureElement(); + boolean isEnabled(); + int openP2pConnection(); + int openTagConnection(); + int selectSecureElement(int seId); + void setOpenTimeout(int timeout); + int setProperties(String param, String value); + +} + diff --git a/core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl b/core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl new file mode 100644 index 0000000000000..79543c41ca4c1 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android; + +import com.trustedlogic.trustednfc.android.NdefMessage; + +/** + * TODO + * + * {@hide} + */ +interface INfcTag +{ + + int close(int nativeHandle); + int connect(int nativeHandle); + String getType(int nativeHandle); + byte[] getUid(int nativeHandle); + boolean isNdef(int nativeHandle); + byte[] transceive(int nativeHandle, in byte[] data); + + NdefMessage read(int nativeHandle); + boolean write(int nativeHandle, in NdefMessage msg); +} \ No newline at end of file diff --git a/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl b/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl new file mode 100644 index 0000000000000..96819ae405b26 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android; + +/** + * TODO + * + * {@hide} + */ +interface IP2pInitiator +{ + + byte[] getGeneralBytes(int nativeHandle); + int getMode(int nativeHandle); + byte[] receive(int nativeHandle); + boolean send(int nativeHandle, in byte[] data); + +} \ No newline at end of file diff --git a/core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl b/core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl new file mode 100644 index 0000000000000..8dcdf18952ee5 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android; + +/** + * TODO + * + * {@hide} + */ +interface IP2pTarget +{ + + byte[] getGeneralBytes(int nativeHandle); + int getMode(int nativeHandle); + int connect(int nativeHandle); + boolean disconnect(int nativeHandle); + byte[] transceive(int nativeHandle, in byte[] data); + +} \ No newline at end of file diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpConnectionlessSocket.java b/core/java/com/trustedlogic/trustednfc/android/LlcpConnectionlessSocket.java new file mode 100644 index 0000000000000..02706267f462a --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/LlcpConnectionlessSocket.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : LlcpConnectionLessSocket.java + * Original-Author : Trusted Logic S.A. (Daniel Tomas) + * Created : 18-02-2010 + */ + +package com.trustedlogic.trustednfc.android; + +import java.io.IOException; + +import com.trustedlogic.trustednfc.android.internal.ErrorCodes; + +import android.os.RemoteException; +import android.util.Log; + +/** + * LlcpConnectionlessSocket represents a LLCP Connectionless object to be used + * in a connectionless communication + * + * @since AA02.01 + * @hide + */ +public class LlcpConnectionlessSocket { + + + private static final String TAG = "LlcpConnectionlessSocket"; + + /** + * The handle returned by the NFC service and used to identify the LLCP connectionless socket in + * every call of this class. + * + * @hide + */ + protected int mHandle; + + + /** + * The entry point for LLCP Connectionless socket operations. + * + * @hide + */ + protected ILlcpConnectionlessSocket mService; + + + /** + * Internal constructor for the LlcpConnectionlessSocket class. + * + * @param service The entry point to the Nfc Service for LLCP Connectionless socket class. + * @param handle The handle returned by the NFC service and used to identify + * the socket in subsequent calls. + * @hide + */ + LlcpConnectionlessSocket(ILlcpConnectionlessSocket service, int handle) { + this.mService = service; + this.mHandle = handle; + } + + /** + * Send data to a specific LLCP Connectionless client + * + * @param packet Service Access Point number related to a LLCP + * Connectionless client and a data buffer to send + * @throws IOException if the LLCP link has been lost or deactivated. + * @since AA02.01 + */ + public void sendTo(LlcpPacket packet) throws IOException { + try { + int result = mService.sendTo(mHandle, packet); + // Handle potential errors + if (ErrorCodes.isError(result)) { + throw new IOException(); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in sendTo(): ", e); + } + } + + /** + * Receive data from a LLCP Connectionless client + * + * @return data data received from a specific LLCP Connectionless client + * @throws IOException if the LLCP link has been lost or deactivated. + * @see LlcpPacket + * @since AA02.01 + */ + public LlcpPacket receiveFrom() throws IOException { + try { + LlcpPacket packet = mService.receiveFrom(mHandle); + if (packet != null) { + return packet; + }else{ + // Handle potential errors + throw new IOException(); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in receiveFrom(): ", e); + } + return null; + } + + /** + * Close the created Connectionless socket. + * + * @since AA02.01 + */ + public void close() { + try { + mService.close(mHandle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in close(): ", e); + } + } + + /** + * Returns the local Service Access Point number of the socket + * + * @return sap + * @since AA02.01 + */ + public int getSap() { + int sap = 0; + + try { + sap = mService.getSap(mHandle); + + } catch (RemoteException e) { + + e.printStackTrace(); + } + return sap; + } +} diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpException.java b/core/java/com/trustedlogic/trustednfc/android/LlcpException.java new file mode 100644 index 0000000000000..1e2e2da6d171a --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/LlcpException.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : LLCPException.java + * Original-Author : Trusted Logic S.A. (Daniel Tomas) + * Created : 24-02-2010 + */ + +package com.trustedlogic.trustednfc.android; + +/** + * Generic exception thrown in case something unexpected happened during a + * LLCP communication. + * + * @since AA02.01 + * @hide + */ +public class LlcpException extends Exception { + /** + * Constructs a new LlcpException with the current stack trace and the + * specified detail message. + * + * @param s the detail message for this exception. + */ + public LlcpException(String s) { + super(s); + } +} diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.aidl b/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.aidl new file mode 100644 index 0000000000000..297a1febce10f --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android; + +parcelable LlcpPacket; diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.java b/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.java new file mode 100644 index 0000000000000..af790230af696 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : LLCPPacket.java + * Original-Author : Trusted Logic S.A. (Daniel Tomas) + * Created : 25-02-2010 + */ + +package com.trustedlogic.trustednfc.android; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Represents a LLCP packet received in a LLCP Connectionless communication; + * + * @since AA02.01 + * @hide + */ +public class LlcpPacket implements Parcelable { + + private int mRemoteSap; + + private byte[] mDataBuffer; + + /** + * Creator class, needed when implementing from Parcelable + * {@hide} + */ + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public LlcpPacket createFromParcel(Parcel in) { + // Remote SAP + short sap = (short)in.readInt(); + + // Data Buffer + int dataLength = in.readInt(); + byte[] data = new byte[dataLength]; + in.readByteArray(data); + + return new LlcpPacket(sap, data); + } + + public LlcpPacket[] newArray(int size) { + return new LlcpPacket[size]; + } + }; + + + /** + * Creates a LlcpPacket to be sent to a remote Service Access Point number + * (SAP) + * + * @param sap Remote Service Access Point number + * @param data Data buffer + * @since AA02.01 + */ + public LlcpPacket(int sap, byte[] data) { + mRemoteSap = sap; + mDataBuffer = data; + } + + /** + * @hide + */ + public LlcpPacket() { + } + + /** + * Returns the remote Service Access Point number + * + * @return remoteSap + * @since AA02.01 + */ + public int getRemoteSap() { + return mRemoteSap; + } + + /** + * Returns the data buffer + * + * @return data + * @since AA02.01 + */ + public byte[] getDataBuffer() { + return mDataBuffer; + } + + /** + * (Parcelable) Describe the parcel + * {@hide} + */ + public int describeContents() { + return 0; + } + + /** + * (Parcelable) Convert current object to a Parcel + * {@hide} + */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mRemoteSap); + dest.writeInt(mDataBuffer.length); + dest.writeByteArray(mDataBuffer); + } +} diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpServiceSocket.java b/core/java/com/trustedlogic/trustednfc/android/LlcpServiceSocket.java new file mode 100644 index 0000000000000..a152ecb1440b6 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/LlcpServiceSocket.java @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : LLCPServerSocket.java + * Original-Author : Trusted Logic S.A. (Daniel Tomas) + * Created : 18-02-2010 + */ + +package com.trustedlogic.trustednfc.android; + +import java.io.IOException; + +import com.trustedlogic.trustednfc.android.internal.ErrorCodes; + +import android.os.RemoteException; +import android.util.Log; + +/** + * LlcpServiceSocket represents a LLCP Service to be used in a + * Connection-oriented communication + * + * @since AA02.01 + * @hide + */ +public class LlcpServiceSocket { + + private static final String TAG = "LlcpServiceSocket"; + + /** + * The handle returned by the NFC service and used to identify the LLCP + * Service socket in every call of this class. + * + * @hide + */ + protected int mHandle; + + /** + * The entry point for LLCP Service socket operations. + * + * @hide + */ + protected ILlcpServiceSocket mService; + + private ILlcpSocket mLlcpSocketService; + + static LlcpException convertErrorToLlcpException(int errorCode) { + return convertErrorToLlcpException(errorCode, null); + } + + static LlcpException convertErrorToLlcpException(int errorCode, + String message) { + if (message == null) { + message = ""; + } else { + message = " (" + message + ")"; + } + + switch (errorCode) { + case ErrorCodes.ERROR_SOCKET_CREATION: + return new LlcpException( + "Error during the creation of an Llcp socket" + message); + case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: + return new LlcpException("Not enough ressources are available" + + message); + default: + return new LlcpException("Unkown error code " + errorCode + message); + } + } + + /** + * Internal constructor for the LlcpServiceSocket class. + * + * @param service + * The entry point to the Nfc Service for LlcpServiceSocket + * class. + * @param handle + * The handle returned by the NFC service and used to identify + * the socket in subsequent calls. + * @hide + */ + LlcpServiceSocket(ILlcpServiceSocket service, ILlcpSocket socketService, int handle) { + this.mService = service; + this.mHandle = handle; + this.mLlcpSocketService = socketService; + } + + /** + * Wait for incomming connection request from a LLCP client and accept this + * request + * + * @return socket object to be used to communicate with a LLCP client + * + * @throws IOException + * if the llcp link is lost or deactivated + * @throws LlcpException + * if not enough ressources are available + * + * @see LlcpSocket + * @since AA02.01 + */ + public LlcpSocket accept() throws IOException, LlcpException { + + try { + int handle = mService.accept(mHandle); + // Handle potential errors + if (ErrorCodes.isError(handle)) { + if (handle == ErrorCodes.ERROR_IO) { + throw new IOException(); + } else { + throw convertErrorToLlcpException(handle); + } + } + + // Build the public LlcpSocket object + return new LlcpSocket(mLlcpSocketService, handle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in accept(): ", e); + return null; + } + + } + + /** + * Set the timeout for the accept request + * + * @param timeout + * value of the timeout for the accept request + * @since AA02.01 + */ + public void setAcceptTimeout(int timeout) { + try { + mService.setAcceptTimeout(mHandle, timeout); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in setAcceptTimeout(): ", e); + } + } + + /** + * Get the timeout value of the accept request + * + * @return mTimeout + * @since AA02.01 + */ + public int getAcceptTimeout() { + try { + return mService.getAcceptTimeout(mHandle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getAcceptTimeout(): ", e); + return 0; + } + } + + /** + * Close the created Llcp Service socket + * + * @since AA02.01 + */ + public void close() { + try { + mService.close(mHandle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in close(): ", e); + } + } + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpSocket.java b/core/java/com/trustedlogic/trustednfc/android/LlcpSocket.java new file mode 100644 index 0000000000000..e47160c84c0bd --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/LlcpSocket.java @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : LlcpClientSocket.java + * Original-Author : Trusted Logic S.A. (Daniel Tomas) + * Created : 18-02-2010 + */ + +package com.trustedlogic.trustednfc.android; + +import java.io.IOException; + +import com.trustedlogic.trustednfc.android.internal.ErrorCodes; + +import android.os.RemoteException; +import android.util.Log; + +/** + * LlcpClientSocket represents a LLCP Connection-Oriented client to be used in a + * connection-oriented communication + * + * @since AA02.01 + * @hide + */ +public class LlcpSocket { + + private static final String TAG = "LlcpSocket"; + + /** + * The handle returned by the NFC service and used to identify the LLCP + * socket in every call of this class. + * + * @hide + */ + protected int mHandle; + + /** + * The entry point for LLCP socket operations. + * + * @hide + */ + protected ILlcpSocket mService; + + static LlcpException convertErrorToLlcpException(int errorCode) { + return convertErrorToLlcpException(errorCode, null); + } + + static LlcpException convertErrorToLlcpException(int errorCode, + String message) { + if (message == null) { + message = ""; + } else { + message = " (" + message + ")"; + } + + switch (errorCode) { + case ErrorCodes.ERROR_SOCKET_CREATION: + return new LlcpException( + "Error during the creation of an Llcp socket" + message); + case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: + return new LlcpException("Not enough ressources are available" + + message); + case ErrorCodes.ERROR_SOCKET_NOT_CONNECTED: + return new LlcpException("Socket not connected to an Llcp Service" + + message); + default: + return new LlcpException("Unkown error code " + errorCode + message); + } + } + + /** + * Internal constructor for the LlcpSocket class. + * + * @param service + * The entry point to the Nfc Service for LlcpServiceSocket + * class. + * @param handle + * The handle returned by the NFC service and used to identify + * the socket in subsequent calls. + * @hide + */ + LlcpSocket(ILlcpSocket service, int handle) { + this.mService = service; + this.mHandle = handle; + } + + /** + * Connect request to a specific LLCP Service by its SAP. + * + * @param sap + * Service Access Point number of the LLCP Service + * @throws IOException + * if the LLCP has been lost or deactivated. + * @throws LlcpException + * if the connection request is rejected by the remote LLCP + * Service + * @since AA02.01 + */ + public void connect(int sap) throws IOException, LlcpException { + try { + int result = mService.connect(mHandle, sap); + // Handle potential errors + if (ErrorCodes.isError(result)) { + if (result == ErrorCodes.ERROR_IO) { + throw new IOException(); + } else { + throw convertErrorToLlcpException(result); + } + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in accept(): ", e); + } + } + + /** + * Connect request to a specific LLCP Service by its Service Name. + * + * @param sn + * Service Name of the LLCP Service + * @throws IOException + * if the LLCP has been lost or deactivated. + * @throws LlcpException + * if the connection request is rejected by the remote LLCP + * Service + * @since AA02.01 + */ + public void connect(String sn) throws IOException, LlcpException { + try { + int result = mService.connectByName(mHandle, sn); + // Handle potential errors + if (ErrorCodes.isError(result)) { + if (result == ErrorCodes.ERROR_IO) { + throw new IOException(); + } else { + throw convertErrorToLlcpException(result); + } + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in accept(): ", e); + } + } + + /** + * Set the timeout for the connect request + * + * @param timeout + * timeout value for the connect request + * @since AA02.01 + */ + public void setConnectTimeout(int timeout) { + try { + mService.setConnectTimeout(mHandle, timeout); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in setConnectTimeout(): ", e); + } + } + + /** + * Get the timeout value of the connect request + * + * @return mTimeout + * @since AA02.01 + */ + public int getConnectTimeout() { + try { + return mService.getConnectTimeout(mHandle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getConnectTimeout(): ", e); + return 0; + } + } + + /** + * Disconnect request to the connected LLCP socket and close the created + * socket. + * + * @throws IOException + * if the LLCP has been lost or deactivated. + * @since AA02.01 + */ + public void close() throws IOException { + try { + int result = mService.close(mHandle); + // Handle potential errors + if (ErrorCodes.isError(result)) { + throw new IOException(); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in close(): ", e); + } + } + + /** + * Send data to the connected LLCP Socket. + * + * @throws IOException + * if the LLCP has been lost or deactivated. + * @since AA02.01 + */ + public void send(byte[] data) throws IOException { + try { + int result = mService.send(mHandle, data); + // Handle potential errors + if (ErrorCodes.isError(result)) { + throw new IOException(); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in send(): ", e); + } + } + + /** + * Receive data from the connected LLCP socket + * + * @param receiveBuffer + * a buffer for the received data + * @return length length of the data received + * @throws IOException + * if the LLCP has been lost or deactivated. + * @since AA02.01 + */ + public int receive(byte[] receiveBuffer) throws IOException { + int receivedLength = 0; + try { + receivedLength = mService.receive(mHandle, receiveBuffer); + if(receivedLength == 0){ + throw new IOException(); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in send(): ", e); + } + + return receivedLength; + } + + /** + * Returns the local Service Access Point number of the socket + * + * @return localSap + * @since AA02.01 + */ + public int getLocalSap() { + try { + return mService.getLocalSap(mHandle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getLocalSap(): ", e); + return 0; + } + } + + /** + * Returns the local Maximum Information Unit(MIU) of the socket + * + * @return miu + * @since AA02.01 + */ + public int getLocalSocketMiu() { + try { + return mService.getLocalSocketMiu(mHandle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getLocalSocketMiu(): ", e); + return 0; + } + } + + /** + * Returns the local Receive Window(RW) of the socket + * + * @return rw + * @since AA02.01 + */ + public int getLocalSocketRw() { + try { + return mService.getLocalSocketRw(mHandle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getLocalSocketRw(): ", e); + return 0; + } + } + + /** + * Returns the remote Maximum Information Unit(MIU) of the socket. + *

+ * This method must be called when the socket is in CONNECTED_STATE + * + * @return remoteMiu + * @throws LlcpException + * if the LlcpClientSocket is not in a CONNECTED_STATE + * @since AA02.01 + */ + public int getRemoteSocketMiu() throws LlcpException { + try { + int result = mService.getRemoteSocketMiu(mHandle); + if(result != ErrorCodes.ERROR_SOCKET_NOT_CONNECTED){ + return result; + }else{ + throw convertErrorToLlcpException(result); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getRemoteSocketMiu(): ", e); + return 0; + } + } + + /** + * Returns the remote Receive Window(RW) of the connected remote socket. + *

+ * This method must be called when the socket is in CONNECTED_STATE + * + * @return rw + * @throws LlcpException + * if the LlcpClientSocket is not in a CONNECTED_STATE + * @since AA02.01 + */ + public int getRemoteSocketRw() throws LlcpException { + try { + int result = mService.getRemoteSocketRw(mHandle); + if( result != ErrorCodes.ERROR_SOCKET_NOT_CONNECTED){ + return result; + }else{ + throw convertErrorToLlcpException(result); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getRemoteSocketRw(): ", e); + return 0; + } + } + + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl b/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl new file mode 100644 index 0000000000000..e60f4e8488acd --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android; + +parcelable NdefMessage; diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.java b/core/java/com/trustedlogic/trustednfc/android/NdefMessage.java new file mode 100644 index 0000000000000..f03b604183f86 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/NdefMessage.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NDEFMessage.java + * Original-Author : Trusted Logic S.A. (Jeremie Corbier) + * Created : 05-10-2009 + */ + +package com.trustedlogic.trustednfc.android; + +import java.util.LinkedList; +import java.util.ListIterator; + +import android.os.Parcel; +import android.os.Parcelable; + +/** + * Represents an NDEF message as specified by the NFC Forum. + * + * @see NdefRecord + * + * @since AA01.04 + * @hide + */ +public class NdefMessage implements Parcelable { + /* Flag values */ + private static final int FLAG_MB = 0x80; + private static final int FLAG_ME = 0x40; + private static final int FLAG_CF = 0x20; + private static final int FLAG_SR = 0x10; + private static final int FLAG_IL = 0x08; + + /** + * Array of {@link NdefRecord} composing this message. + */ + private NdefRecord[] mRecords; + + /** + * Builds an NDEF message. + * + * @param data raw NDEF message data + * + * @throws NFCException + */ + public NdefMessage(byte[] data) throws NfcException { + if (parseNdefMessage(data) == -1) + throw new NfcException("Error while parsing NDEF message"); + } + + /** + * Builds an NDEF message. + * + * @param records + * an array of already created NDEF records + */ + public NdefMessage(NdefRecord[] records) { + mRecords = new NdefRecord[records.length]; + + System.arraycopy(records, 0, mRecords, 0, records.length); + } + + /** + * Returns the NDEF message as a byte array. + * + * @return the message as a byte array + */ + public byte[] toByteArray() { + if ((mRecords == null) || (mRecords.length == 0)) + return null; + + byte[] msg = {}; + + for (int i = 0; i < mRecords.length; i++) { + byte[] record = mRecords[i].toByteArray(); + byte[] tmp = new byte[msg.length + record.length]; + + /* Make sure the Message Begin flag is set only for the first record */ + if (i == 0) + record[0] |= FLAG_MB; + else + record[0] &= ~FLAG_MB; + + /* Make sure the Message End flag is set only for the last record */ + if (i == (mRecords.length - 1)) + record[0] |= FLAG_ME; + else + record[0] &= ~FLAG_ME; + + System.arraycopy(msg, 0, tmp, 0, msg.length); + System.arraycopy(record, 0, tmp, msg.length, record.length); + + msg = tmp; + } + + return msg; + } + + /** + * Returns an array of {@link NdefRecord} composing this message. + * + * @return mRecords + * + * @since AA02.01 + */ + public NdefRecord[] getRecords(){ + return mRecords; + } + + private native int parseNdefMessage(byte[] data); + + /** + * (Parcelable) Describe the parcel + * {@hide} + */ + public int describeContents() { + return 0; + } + + /** + * (Parcelable) Convert current object to a Parcel + * {@hide} + */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mRecords.length); + dest.writeTypedArray(mRecords, 0); + } + + /** + * Creator class, needed when implementing from Parcelable + * {@hide} + */ + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public NdefMessage createFromParcel(Parcel in) { + int recordsLength = in.readInt(); + NdefRecord[] records = new NdefRecord[recordsLength]; + in.readTypedArray(records, NdefRecord.CREATOR); + return new NdefMessage(records); + } + + public NdefMessage[] newArray(int size) { + return new NdefMessage[size]; + } + }; + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefRecord.aidl b/core/java/com/trustedlogic/trustednfc/android/NdefRecord.aidl new file mode 100644 index 0000000000000..9d95174b68536 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/NdefRecord.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android; + +parcelable NdefRecord; diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefRecord.java b/core/java/com/trustedlogic/trustednfc/android/NdefRecord.java new file mode 100644 index 0000000000000..a0257feffc0c7 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/NdefRecord.java @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NdefRecord.java + * Original-Author : Trusted Logic S.A. (Jeremie Corbier) + * Created : 05-10-2009 + */ + +package com.trustedlogic.trustednfc.android; + +import android.location.Location; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * An NDEF record as specified by the NFC + * Forum. + * + * @see NdefMessage + * + * @since AA01.04 + * @hide + */ +public class NdefRecord implements Parcelable { + + /** + * Type Name Format - Empty record + */ + public static final short TNF_EMPTY = 0x0; + + /** + * Type Name Format - NFC Forum-defined type + */ + public static final short TNF_WELL_KNOWN_TYPE = 0x1; + + /** + * Type Name Format - RFC2045 MIME type + */ + public static final short TNF_MIME_MEDIA_TYPE = 0x2; + + /** + * Type Name Format - Absolute URI + */ + public static final short TNF_ABSOLUTE_URI = 0x3; + + /** + * Type Name Format - User-defined type + */ + public static final short TNF_EXTERNAL_TYPE = 0x4; + + /** + * Type Name Format - Unknown type + */ + public static final short TNF_UNKNOWN = 0x5; + + /** + * Type Name Format - Unchanged. This TNF is used for chunked records, so + * that middle records inherits from the first record's type. + */ + public static final short TNF_UNCHANGED = 0x6; + + /** + * NFC Forum-defined Type - Smart Poster + */ + public static final byte[] TYPE_SMART_POSTER = { 0x53, 0x70 }; + + /** + * NFC Forum-defined Type - Text + */ + public static final byte[] TYPE_TEXT = { 0x54 }; + + /** + * NFC Forum-defined Type - URI + */ + public static final byte[] TYPE_URI = { 0x55 }; + + /** + * NFC Forum-defined Global Type - Connection Handover Request + */ + public static final byte[] TYPE_HANDOVER_REQUEST = { 0x48, 0x72 }; + + /** + * NFC Forum-defined Global Type - Connection Handover Select + */ + public static final byte[] TYPE_HANDOVER_SELECT = { 0x48, 0x73 }; + + /** + * NFC Forum-defined Global Type - Connection Handover Carrier + */ + public static final byte[] TYPE_HANDOVER_CARRIER = { 0x48, 0x63 }; + + /** + * NFC Forum-defined Local Type - Alternative Carrier + */ + public static final byte[] TYPE_ALTERNATIVE_CARRIER = { 0x61, 0x63 }; + + /* Flag values */ + private static final int FLAG_MB = 0x80; + private static final int FLAG_ME = 0x40; + private static final int FLAG_CF = 0x20; + private static final int FLAG_SR = 0x10; + private static final int FLAG_IL = 0x08; + + /** + * Record Flags + */ + private short mFlags = 0; + + /** + * Record Type Name Format + */ + private short mTnf = 0; + + /** + * Record Type + */ + private byte[] mType = null; + + /** + * Record Identifier + */ + private byte[] mId = null; + + /** + * Record Payload + */ + private byte[] mPayload = null; + + /** + * Creates an NdefRecord given its Type Name Format, its type, its id and + * its. + * + * @param tnf + * Type Name Format + * @param type + * record type + * @param id + * record id (optional, can be null) + * @param data + * record payload + */ + public NdefRecord(short tnf, byte[] type, byte[] id, byte[] data) { + + /* generate flag */ + mFlags = FLAG_MB | FLAG_ME; + + /* Determine if it is a short record */ + if(data.length < 0xFF) + { + mFlags |= FLAG_SR; + } + + /* Determine if an id is present */ + if(id.length != 0) + { + mFlags |= FLAG_IL; + } + + mTnf = tnf; + mType = (byte[]) type.clone(); + mId = (byte[]) id.clone(); + mPayload = (byte[]) data.clone(); + } + + /** + * Appends data to the record's payload. + * + * @param data + * Data to be added to the record. + */ + public void appendPayload(byte[] data) { + byte[] newPayload = new byte[mPayload.length + data.length]; + + System.arraycopy(mPayload, 0, newPayload, 0, mPayload.length); + System.arraycopy(data, 0, newPayload, mPayload.length, data.length); + + mPayload = newPayload; + } + + /** + * Returns record as a byte array. + * + * @return record as a byte array. + */ + public byte[] toByteArray() { + return generate(mFlags, mTnf, mType, mId, mPayload); + } + + private native byte[] generate(short flags, short tnf, byte[] type, + byte[] id, byte[] data); + + /** + * (Parcelable) Describe the parcel + * {@hide} + */ + public int describeContents() { + return 0; + } + + /** + * (Parcelable) Convert current object to a Parcel + * {@hide} + */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mTnf); + dest.writeInt(mType.length); + dest.writeByteArray(mType); + dest.writeInt(mId.length); + dest.writeByteArray(mId); + dest.writeInt(mPayload.length); + dest.writeByteArray(mPayload); + } + + /** + * Creator class, needed when implementing from Parcelable + * {@hide} + */ + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public NdefRecord createFromParcel(Parcel in) { + // TNF + short tnf = (short)in.readInt(); + // Type + int typeLength = in.readInt(); + byte[] type = new byte[typeLength]; + in.readByteArray(type); + // ID + int idLength = in.readInt(); + byte[] id = new byte[idLength]; + in.readByteArray(id); + // Payload + int payloadLength = in.readInt(); + byte[] payload = new byte[payloadLength]; + in.readByteArray(payload); + + return new NdefRecord(tnf, type, id, payload); + } + + public NdefRecord[] newArray(int size) { + return new NdefRecord[size]; + } + }; + + /** + * Returns record TNF + * + * @return mTnf + */ + public int getTnf(){ + return mTnf; + } + + /** + * Returns record TYPE + * + * @return mType + */ + public byte[] getType(){ + return mType; + } + + /** + * Returns record ID + * + * @return mId + */ + public byte[] getId(){ + return mId; + } + + /** + * Returns record Payload + * + * @return mPayload + */ + public byte[] getPayload(){ + return mPayload; + } + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefTag.java b/core/java/com/trustedlogic/trustednfc/android/NdefTag.java new file mode 100644 index 0000000000000..1d992414d2119 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/NdefTag.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NDEFTag.java + * Original-Author : Trusted Logic S.A. (Jeremie Corbier) + * Created : 04-12-2009 + */ + +package com.trustedlogic.trustednfc.android; + +import java.io.IOException; + +import android.os.RemoteException; +import android.util.Log; + +/** + * NdefTag represents tags complying with the NFC Forum's NFC Data Exchange + * Format. + * + * @since AA01.04 + * @hide + */ +public class NdefTag extends NfcTag { + + private static final String TAG = "NdefTag"; + + + public NdefTag(NfcTag tag){ + super(tag.mService,tag.mHandle); + this.isConnected = tag.isConnected; + this.isClosed = tag.isClosed; + tag.isClosed = false; + } + + /** + * Internal constructor for the NfcNdefTag class. + * + * @param service The entry point to the Nfc Service for NfcNdefTag class. + * @param handle The handle returned by the NFC service and used to identify + * the tag in subsequent calls. + * @hide + */ + NdefTag(INfcTag service, int handle) { + super(service, handle); + } + + /** + * Read NDEF data from an NDEF tag. + * + * @return the NDEF message read from the tag. + * @throws NfcException if the tag is not NDEF-formatted. + * @throws IOException if the target has been lost or the connection has + * been closed. + * @see NdefMessage + */ + public NdefMessage read() throws NfcException, IOException { + // Check state + checkState(); + + //Check if the tag is Ndef compliant + if(isNdef != true){ + isNdef = isNdef(); + if(isNdef != true) { + throw new NfcException("Tag is not NDEF compliant"); + } + } + + // Perform transceive + try { + NdefMessage msg = mService.read(mHandle); + if (msg == null) { + throw new IOException("NDEF read failed"); + } + return msg; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in read(): ", e); + return null; + } + } + + /** + * Write NDEF data to an NDEF-compliant tag. + * + * @param msg NDEF message to be written to the tag. + * @throws NfcException if the tag is not NDEF formatted. + * @throws IOException if the target has been lost or the connection has + * been closed. + * @see NdefMessage + */ + public void write(NdefMessage msg) throws NfcException, IOException { + // Check state + checkState(); + + //Check if the tag is Ndef compliant + if(isNdef != true){ + isNdef = isNdef(); + if(isNdef != true) { + throw new NfcException("Tag is not NDEF compliant"); + } + } + + // Perform transceive + try { + boolean isSuccess = mService.write(mHandle, msg); + if (!isSuccess) { + throw new IOException("NDEF write failed"); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in write(): ", e); + } + } +} diff --git a/core/java/com/trustedlogic/trustednfc/android/NfcException.java b/core/java/com/trustedlogic/trustednfc/android/NfcException.java new file mode 100644 index 0000000000000..2497c15f480ed --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/NfcException.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NFCException.java + * Original-Author : Trusted Logic S.A. (Jeremie Corbier) + * Created : 26-08-2009 + */ + +package com.trustedlogic.trustednfc.android; + +/** + * Generic exception thrown in case something unexpected happened during the + * NFCManager operations. + * + * @since AA01.04 + * @hide + */ +public class NfcException extends Exception { + /** + * Constructs a new NfcException with the current stack trace and the + * specified detail message. + * + * @param s the detail message for this exception. + */ + public NfcException(String s) { + super(s); + } +} diff --git a/core/java/com/trustedlogic/trustednfc/android/NfcManager.java b/core/java/com/trustedlogic/trustednfc/android/NfcManager.java new file mode 100644 index 0000000000000..98ab5bf4b13db --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/NfcManager.java @@ -0,0 +1,656 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NfcManager.java + * Original-Author : Trusted Logic S.A. (Jeremie Corbier) + * Created : 26-08-2009 + */ + +package com.trustedlogic.trustednfc.android; + +import java.io.IOException; + +import com.trustedlogic.trustednfc.android.internal.ErrorCodes; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.media.MiniThumbFile; +import android.os.Handler; +import android.os.RemoteException; +import android.util.Log; + +//import android.util.Log; + +/** + * This class provides the primary API for managing all aspects of NFC. Get an + * instance of this class by calling + * Context.getSystemService(Context.NFC_SERVICE). + * @hide + */ +public final class NfcManager { + /** + * Tag Reader Discovery mode + */ + private static final int DISCOVERY_MODE_TAG_READER = 0; + + /** + * NFC-IP1 Peer-to-Peer mode Enables the manager to act as a peer in an + * NFC-IP1 communication. Implementations should not assume that the + * controller will end up behaving as an NFC-IP1 target or initiator and + * should handle both cases, depending on the type of the remote peer type. + */ + private static final int DISCOVERY_MODE_NFCIP1 = 1; + + /** + * Card Emulation mode Enables the manager to act as an NFC tag. Provided + * that a Secure Element (an UICC for instance) is connected to the NFC + * controller through its SWP interface, it can be exposed to the outside + * NFC world and be addressed by external readers the same way they would + * with a tag. + *

+ * Which Secure Element is exposed is implementation-dependent. + * + * @since AA01.04 + */ + private static final int DISCOVERY_MODE_CARD_EMULATION = 2; + + /** + * Used as Parcelable extra field in + * {@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_TAG_DISCOVERED_ACTION} + * . It contains the NDEF message read from the NDEF tag discovered. + */ + public static final String NDEF_MESSAGE_EXTRA = "com.trustedlogic.trustednfc.android.extra.NDEF_MESSAGE"; + + /** + * Broadcast Action: a NDEF tag has been discovered. + *

+ * Always contains the extra field + * {@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_MESSAGE_EXTRA}. + *

+ * Note: Requires the NFC_NOTIFY permission. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String NDEF_TAG_DISCOVERED_ACTION = "com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED"; + + /** + * Used as byte array extra field in + * {@link com.trustedlogic.trustednfc.android.NfcManager#TRANSACTION_DETECTED_ACTION} + * . It contains the AID of the applet concerned by the transaction. + */ + public static final String AID_EXTRA = "com.trustedlogic.trustednfc.android.extra.AID"; + + /** + * Broadcast Action: a transaction with a secure element has been detected. + *

+ * Always contains the extra field + * {@link com.trustedlogic.trustednfc.android.NfcManager#AID_EXTRA} + *

+ * Note: Requires the NFC_NOTIFY permission + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String TRANSACTION_DETECTED_ACTION = "com.trustedlogic.trustednfc.android.action.TRANSACTION_DETECTED"; + + /** + * LLCP link status: The LLCP link is activated. + * + * @since AA02.01 + */ + public static final int LLCP_LINK_STATE_ACTIVATED = 0; + + /** + * LLCP link status: The LLCP link is deactivated. + * + * @since AA02.01 + */ + public static final int LLCP_LINK_STATE_DEACTIVATED = 1; + + /** + * Used as int extra field in + * {@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_ACTION} + * . It contains the new state of the LLCP link. + */ + public static final String LLCP_LINK_STATE_CHANGED_EXTRA = "com.trustedlogic.trustednfc.android.extra.LLCP_LINK_STATE"; + + /** + * Broadcast Action: the LLCP link state changed. + *

+ * Always contains the extra field + * {@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_EXTRA}. + *

+ * Note: Requires the NFC_LLCP permission. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String LLCP_LINK_STATE_CHANGED_ACTION = "com.trustedlogic.trustednfc.android.action.LLCP_LINK_STATE_CHANGED"; + + private static final String TAG = "NfcManager"; + + private Handler mHandler; + + private INfcManager mService; + + private INfcTag mNfcTagService; + + private IP2pTarget mP2pTargetService; + + private IP2pInitiator mP2pInitiatorService; + + private ILlcpSocket mLlcpSocketService; + + private ILlcpConnectionlessSocket mLlcpConnectionlessSocketService; + + private ILlcpServiceSocket mLlcpServiceSocketService; + + static NfcException convertErrorToNfcException(int errorCode) { + return convertErrorToNfcException(errorCode, null); + } + + static NfcException convertErrorToNfcException(int errorCode, String message) { + if (message == null) { + message = ""; + } else { + message = " (" + message + ")"; + } + + switch (errorCode) { + case ErrorCodes.ERROR_BUSY: + return new NfcException("Another operation is already pending" + message); + case ErrorCodes.ERROR_CANCELLED: + return new NfcException("Operation cancelled" + message); + case ErrorCodes.ERROR_TIMEOUT: + return new NfcException("Operation timed out" + message); + case ErrorCodes.ERROR_SOCKET_CREATION: + return new NfcException("Error during the creation of an Llcp socket:" + message); + case ErrorCodes.ERROR_SAP_USED: + return new NfcException("Error SAP already used:" + message); + case ErrorCodes.ERROR_SERVICE_NAME_USED: + return new NfcException("Error Service Name already used:" + message); + case ErrorCodes.ERROR_SOCKET_OPTIONS: + return new NfcException("Error Socket options:" + message); + case ErrorCodes.ERROR_INVALID_PARAM: + return new NfcException("Error Set Properties: invalid param" + message); + case ErrorCodes.ERROR_NFC_ON: + return new NfcException("Error Set Properties : NFC is ON" + message); + case ErrorCodes.ERROR_NOT_INITIALIZED: + return new NfcException("NFC is not running " + message); + case ErrorCodes.ERROR_SE_ALREADY_SELECTED: + return new NfcException("Secure Element already connected" + message); + case ErrorCodes.ERROR_NO_SE_CONNECTED: + return new NfcException("No Secure Element connected" + message); + case ErrorCodes.ERROR_SE_CONNECTED: + return new NfcException("A secure Element is already connected" + message); + default: + return new NfcException("Unkown error code " + errorCode + message); + } + } + + /** + * @hide + */ + public NfcManager(INfcManager service, Handler handler) { + mService = service; + mHandler = handler; + try { + mNfcTagService = mService.getNfcTagInterface(); + mP2pInitiatorService = mService.getP2pInitiatorInterface(); + mP2pTargetService = mService.getP2pTargetInterface(); + mLlcpServiceSocketService = mService.getLlcpServiceInterface(); + mLlcpConnectionlessSocketService = mService.getLlcpConnectionlessInterface(); + mLlcpSocketService = mService.getLlcpInterface(); + } catch (RemoteException e) { + mLlcpSocketService = null; + mNfcTagService = null; + mP2pInitiatorService = null; + mP2pTargetService = null; + mLlcpConnectionlessSocketService = null; + mLlcpServiceSocketService = null; + } + } + + /** + * Return the status of the NFC feature + * + * @return mIsNfcEnabled + * @since AA02.01 + */ + public boolean isEnabled() { + try { + return mService.isEnabled(); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in isEnabled(): ", e); + return false; + } + } + + /** + * Enable the NFC Feature + *

+ * Note: Requires the NFC_ADMIN permission + * + * @throws NfcException if the enable failed + * @since AA02.01 + */ + public void enable() throws NfcException { + try { + boolean isSuccess = mService.enable(); + if (isSuccess == false) { + throw new NfcException("NFC Service failed to enable"); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in enable(): ", e); + } + } + + /** + * Disable the NFC feature + *

+ * Note: Requires the NFC_ADMIN permission + * + * @throws NfcException if the disable failed + * @since AA02.01 + */ + public void disable() throws NfcException { + try { + boolean isSuccess = mService.disable(); + if (isSuccess == false) { + throw new NfcException("NFC Service failed to disable"); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in disable(): ", e); + } + } + + /** + * Get the list of the identifiers of the Secure Elements detected + * by the NFC controller. + * + * @return list a list of Secure Element identifiers. + * @see #getSelectedSecureElement + * @see #selectSecureElement(int) + * @see #deselectSecureElement + * @since AA02.01 + */ + public int[] getSecureElementList() { + try { + return mService.getSecureElementList(); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getSecureElementList(): ", e); + return null; + } + } + + /** + * Get the identifier of the currently selected secure element. + * + * @return id identifier of the currently selected Secure Element. 0 if none. + * @see #getSecureElementList + * @see #selectSecureElement(int) + * @see #deselectSecureElement + * @since AA02.01 + */ + public int getSelectedSecureElement() { + try { + return mService.getSelectedSecureElement(); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getSelectedSecureElement(): ", e); + return -1; + } + } + + /** + * Select a specific Secure Element by its identifier. + *

+ * Note: Requires the NFC_ADMIN permission + * + * @throws NfcException if a or this secure element is already selected + * @see #getSecureElementList + * @see #getSelectedSecureElement + * @see #deselectSecureElement + * @since AA02.01 + */ + public void selectSecureElement(int seId) throws NfcException { + try { + int status = mService.selectSecureElement(seId); + if(status != ErrorCodes.SUCCESS){ + throw convertErrorToNfcException(status); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in selectSecureElement(): ", e); + } + } + + /** + * Deselect the currently selected Secure Element + *

+ * Note: Requires the NFC_ADMIN permission + * + * @throws NfcException if no secure Element is selected + * @see #getSecureElementList + * @see #getSelectedSecureElement + * @see #selectSecureElement(int) + * @since AA02.01 + */ + public void deselectSecureElement() throws NfcException { + try { + int status = mService.deselectSecureElement(); + if(status != ErrorCodes.SUCCESS){ + throw convertErrorToNfcException(status); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in deselectSecureElement(): ", e); + } + } + + /** + * Open a connection with a remote NFC peer + * + * This method does not return while no remote NFC peer enters the field. + *

+ * Note: Requires the NFC_RAW permission + * + * @return P2pDevice object to be used to communicate with the detected + * peer. + * @throws IOException if the target has been lost or the connection has + * been closed. + * @throws NfcException if an open is already started + * @see P2pDevice + * @see #getOpenTimeout + * @see #setOpenTimeout(int) + * @see #cancel + * @since AA02.01 + */ + public P2pDevice openP2pConnection() throws IOException, NfcException { + try { + int handle = mService.openP2pConnection(); + // Handle potential errors + if (ErrorCodes.isError(handle)) { + if (handle == ErrorCodes.ERROR_IO) { + throw new IOException(); + } else { + throw convertErrorToNfcException(handle); + } + } + // Build the public NfcTag object, depending on its type + if (mP2pTargetService.getMode(handle) == P2pDevice.MODE_P2P_TARGET) { + return new P2pTarget(mP2pTargetService, handle); + } else { + return new P2pInitiator(mP2pInitiatorService, handle); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in openTagConnection(): ", e); + return null; + } + } + + /** + * Open a connection with a tag + * + * This method does not return while no tag enters the field. + *

+ * Note: Requires the NFC_RAW permission + * + * @return tag object to be use to communicate with the detected NfcTag. + * @throws IOException if the target has been lost or the connection has + * been closed. + * @throws NfcException if an open is already started + * @see NfcTag + * @see #getOpenTimeout + * @see #setOpenTimeout(int) + * @see #cancel + * @since AA02.01 + */ + public NfcTag openTagConnection() throws IOException, NfcException { + try { + int handle = mService.openTagConnection(); + // Handle potential errors + if (ErrorCodes.isError(handle)) { + if (handle == ErrorCodes.ERROR_IO) { + throw new IOException(); + } else { + throw convertErrorToNfcException(handle); + } + } + // Build the public NfcTag object + return new NfcTag(mNfcTagService, handle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in openTagConnection(): ", e); + return null; + } + } + + /** + * Set the timeout for open requests + *

+ * Note: Requires the NFC_RAW permission + * + * @param timeout value of the timeout for open request + * @see #openP2pConnection + * @see #openTagConnection + * @see #getOpenTimeout + * @since AA02.01 + */ + public void setOpenTimeout(int timeout) { + try { + mService.setOpenTimeout(timeout); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in setOpenTimeout(): ", e); + } + } + + /** + * Get the timeout value of open requests + * + * @return mTimeout + * @see #setOpenTimeout(int) + * @since AA02.01 + */ + public int getOpenTimeout() { + try { + return mService.getOpenTimeout(); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getOpenTimeout(): ", e); + return 0; + } + } + + /** + * Cancel an openTagConnection or an openP2pConnection started + *

+ * Note: Requires the NFC_RAW permission + * + * @see #openP2pConnection + * @see #openTagConnection + * @since AA02.01 + */ + public void cancel() { + try { + mService.cancel(); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in cancel(): ", e); + } + } + + /** + * Creates a connectionless socket for a LLCP link and set its Service + * Access Point number (SAP) + *

+ * Note: Requires the NFC_LLCP permission + * + * @param sap Service Access Point number related to the created + * Connectionless socket. + * @return LlcpConnectionlessSocket object to be used in a LLCP + * Connectionless communication. + * @throws IOException if the socket creation failed + * @throws NfcException if socket ressources are insufficicent + * @see LlcpConnectionlessSocket + * @since AA02.01 + */ + public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int sap) throws IOException, + NfcException { + + try { + int handle = mService.createLlcpConnectionlessSocket(sap); + // Handle potential errors + if (ErrorCodes.isError(handle)) { + if (handle == ErrorCodes.ERROR_IO) { + throw new IOException(); + } else { + throw convertErrorToNfcException(handle); + } + } + + // Build the public LlcpConnectionLess object + return new LlcpConnectionlessSocket(mLlcpConnectionlessSocketService, handle); + + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in createLlcpConnectionlessSocket(): ", e); + return null; + } + } + + /** + * Creates a LlcpServiceSocket for a LLCP link, set its Service Access Point + * number (SAP). + *

+ * During a LLCP communication, the LlcpServiceSocket will create LlcpSocket + * to communicate with incoming LLCP clients. For that, a server socket need + * to have some informations as a working buffer length in order to handle + * incoming data and some options to define the LLCP communication. + *

+ * Note: Requires the NFC_LLCP permission + * + * @param sap + * @param sn Service Name of the LlcpServiceSocket + * @param miu Maximum Information Unit (MIU) for a LlcpSocket created by the + * LlcpServiceSocket + * @param rw Receive Window (RW) for a LlcpSocket created by the + * LlcpServiceSocket + * @param linearBufferLength size of the memory space needed to handle + * incoming data for every LlcpSocket created. + * @return LlcpServiceSocket object to be used as a LLCP Service in a + * connection oriented communication. + * @throws IOException if the socket creation failed + * @throws NfcException if socket ressources are insufficicent + * @see LlcpServiceSocket + * @since AA02.01 + */ + public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw, + int linearBufferLength) throws IOException, NfcException { + try { + int handle = mService.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength); + // Handle potential errors + if (ErrorCodes.isError(handle)) { + if (handle == ErrorCodes.ERROR_IO) { + throw new IOException(); + } else { + throw convertErrorToNfcException(handle); + } + } + + // Build the public LlcpServiceSocket object + return new LlcpServiceSocket(mLlcpServiceSocketService, mLlcpSocketService, handle); + + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in createLlcpServiceSocket(): ", e); + return null; + } + } + + /** + * Creates a LlcpSocket for a LLCP link with a specific Service Access Point + * number (SAP) + *

+ * A LlcpSocket need to have a linear buffer in order to handle incoming + * data. This linear buffer will be used to store incoming data as a stream. + * Data will be readable later. + *

+ * Note: Requires the NFC_LLCP permission + * + * @param sap Service Access Point number for the created socket + * @param miu Maximum Information Unit (MIU) of the communication socket + * @param rw Receive Window (RW) of the communication socket + * @param linearBufferLength size of the memory space needed to handle + * incoming data with this socket + * @throws IOException if the socket creation failed + * @throws NfcException if socket ressources are insufficicent + * @see LlcpSocket + * @since AA02.01 + */ + public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) + throws IOException, NfcException { + try { + int handle = mService.createLlcpSocket(sap, miu, rw, linearBufferLength); + // Handle potential errors + if (ErrorCodes.isError(handle)) { + if (handle == ErrorCodes.ERROR_IO) { + throw new IOException(); + } else { + throw convertErrorToNfcException(handle); + } + } + // Build the public LlcpSocket object + return new LlcpSocket(mLlcpSocketService, handle); + + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in createLlcpSocket(): ", e); + return null; + } + } + + /** + * Set different parameters like the NCIP General bytes, the LLCP link + * parameters and all tag discovery parameters. + *

+ * Note: Requires the NFC_ADMIN permission + * + * @param param parameter to be updated with a new value + * @param value new value of the parameter + * @throws NfcException if incorrect parameters of NFC is ON + * @since AA02.01 + */ + public void setProperties(String param, String value) throws NfcException { + try { + int result = mService.setProperties(param, value); + // Handle potential errors + if (ErrorCodes.isError(result)) { + throw convertErrorToNfcException(result); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in setProperties(): ", e); + } + } + + /** + * Get the value of different parameters like the NCFIP General bytes, the + * LLCP link parameters and all tag discovery parameters. + * + * @param param parameter to be updated + * @return String value of the requested parameter + * @throws RemoteException + * @since AA02.01 + */ + public String getProperties(String param) { + String value; + try { + value = mService.getProperties(param); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getProperties(): ", e); + return null; + } + return value; + } + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/NfcTag.java b/core/java/com/trustedlogic/trustednfc/android/NfcTag.java new file mode 100644 index 0000000000000..798c7e4c6bd79 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/NfcTag.java @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NFCTag.java + * Original-Author : Trusted Logic S.A. (Daniel Tomas) + * Created : 26-02-2010 + */ + +package com.trustedlogic.trustednfc.android; + +import java.io.IOException; + +import android.os.RemoteException; +import android.util.Log; + +import com.trustedlogic.trustednfc.android.internal.ErrorCodes; + +/** + * This class represents tags with no known formatting. One can use the method + * {@link #isNdef()} to determine if the tag can store NDEF-formatted messages. + *

+ * + *

+ * if (tag.isNdef()) {
+ *     NdefTag ndefTag = (NdefTag) tag;
+ *     NdefMessage msg = ndefTag.read();
+ * }
+ * 
+ * + * @since AA01.04 + * @see NdefMessage + * @hide + */ +public class NfcTag { + + private static final String TAG = "NfcTag"; + + /** + * The handle returned by the NFC service and used to identify the tag in + * every call of this class. + * + * @hide + */ + protected int mHandle; + + /** + * The entry point for tag operations. + * + * @hide + */ + protected INfcTag mService; + + /** + * Flag set when the object is closed and thus not usable any more. + * + * @hide + */ + protected boolean isClosed = false; + + /** + * Flag set when the tag is connected. + * + * @hide + */ + protected boolean isConnected = false; + + /** + * Flag set when a check NDEF is performed. + * + * @hide + */ + protected boolean isNdef = false; + + /** + * Check if tag is still opened. + * + * @return data sent by the P2pInitiator. + * @throws NfcException if accessing a closed target. + * + * @hide + */ + public void checkState() throws NfcException { + if (isClosed) { + throw new NfcException("Tag has been closed."); + } + if (!isConnected) { + throw new NfcException("Tag is not connected."); + } + } + + /** + * Internal constructor for the NfcTag class. + * + * @param service The entry point to the Nfc Service for NfcTag class. + * @param handle The handle returned by the NFC service and used to identify + * the tag in subsequent calls. + * @hide + */ + NfcTag(INfcTag service, int handle) { + this.mService = service; + this.mHandle = handle; + } + + /** + * Connects to the tag. This shall be called prior to any other operation on + * the tag. + * + * @throws IOException if the tag has been lost or the connection has been + * closed. + * @throws nfcException if the tag is already in connected state. + */ + public void connect() throws NfcException, IOException { + // Check state + if (isClosed) { + throw new NfcException("Tag has been closed."); + } + if (isConnected) { + throw new NfcException("Already connected"); + } + + // Perform connect + try { + int result = mService.connect(mHandle); + if (ErrorCodes.isError(result)) { + if (result == ErrorCodes.ERROR_IO) { + throw new IOException("Failed to connect"); + } + else { + throw NfcManager.convertErrorToNfcException(result); + } + } + isConnected = true; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in connect(): ", e); + } + } + + /** + * Disconnects from the tag. This must be called so that other targets can + * be discovered. It restarts the NFC discovery loop. + * + * @throws NfcException if the tag is already in disconnected state or not connected + */ + public void close() throws NfcException { + // Check state + checkState(); + + try { + mService.close(mHandle); + isClosed = true; + isConnected = false; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in close(): ", e); + } + } + + /** + * Exchanges raw data with the tag, whatever the tag type. + * + * To exchange APDUs with a ISO14443-4-compliant tag, the data parameter + * must be filled with the C-APDU (CLA, INS, P1, P2 [, ...]). The returned + * data consists of the R-APDU ([...,] SW1, SW2). + * + * @param data data to be sent to the tag + * @return data sent in response by the tag + * @throws IOException if the tag has been lost or the connection has been + * closed. + * @throws NfcException in case of failure within the stack + */ + public byte[] transceive(byte[] data) throws IOException, NfcException { + // Check state + checkState(); + + // Perform transceive + try { + byte[] response = mService.transceive(mHandle, data); + if (response == null) { + throw new IOException("Transceive failed"); + } + return response; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in transceive(): ", e); + return null; + } + } + + /** + * Checks whether tag is NDEF-compliant or not. + * + * @return true if the tag is NDEF-compliant, false otherwise + * @throws NfcException in case an error occurred when trying to determine + * whether the tag is NDEF-compliant + */ + public boolean isNdef() throws NfcException { + // Check state + checkState(); + + // Perform Check Ndef + try { + isNdef = mService.isNdef(mHandle); + return isNdef; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in isNdef(): ", e); + return false; + } + } + + /** + * Returns target type. constants. + * + * @return tag type. + */ + public String getType() { + try { + return mService.getType(mHandle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getType(): ", e); + return null; + } + } + + /** + * Returns target UID. + * + * @return tag UID. + */ + public byte[] getUid() { + try { + return mService.getUid(mHandle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getType(): ", e); + return null; + } + } + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/P2pDevice.java b/core/java/com/trustedlogic/trustednfc/android/P2pDevice.java new file mode 100644 index 0000000000000..65800f29960b3 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/P2pDevice.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : P2PDevice.java + * Original-Author : Trusted Logic S.A. (Daniel Tomas) + * Created : 26-02-2010 + */ + +package com.trustedlogic.trustednfc.android; + +import java.io.IOException; + +/** + * P2pDevice is the abstract base class for all supported P2P targets the + * NfcManager can handle. + * @hide + */ +public abstract class P2pDevice { + + /** + * Peer-to-Peer Target. + */ + public static final short MODE_P2P_TARGET = 0x00; + + /** + * Peer-to-Peer Initiator. + */ + public static final short MODE_P2P_INITIATOR = 0x01; + + /** + * Invalid target type. + */ + public static final short MODE_INVALID = 0xff; + + /** + * Target handle, used by native calls. + * @hide + */ + protected int mHandle; + + /** + * Flag set when the object is closed and thus not usable any more. + * @hide + */ + protected boolean isClosed = false; + + /** + * Prevent default constructor to be public. + * @hide + */ + protected P2pDevice() { + } + + /** + * Returns the remote NFC-IP1 General Bytes. + * + * @return remote general bytes + * @throws IOException + */ + public byte[] getGeneralBytes() throws IOException { + // Should not be called directly (use subclasses overridden method instead) + return null; + } + + /** + * Returns target type. The value returned can be one of the TYPE_* + * constants. + * + * @return target type. + */ + public int getMode() { + // Should not be called directly (use subclasses overridden method instead) + return MODE_INVALID; + } +} diff --git a/core/java/com/trustedlogic/trustednfc/android/P2pInitiator.java b/core/java/com/trustedlogic/trustednfc/android/P2pInitiator.java new file mode 100644 index 0000000000000..0f28ae0131d86 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/P2pInitiator.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : P2PInitiator.java + * Original-Author : Trusted Logic S.A. (Daniel Tomas) + */ + +package com.trustedlogic.trustednfc.android; + +import java.io.IOException; + +import com.trustedlogic.trustednfc.android.internal.ErrorCodes; + +import android.os.RemoteException; +import android.util.Log; + +/** + * P2pInitiator represents the initiator in an NFC-IP1 peer-to-peer + * communication. + * + * @see P2pTarget + * @since AA02.01 + * @hide + */ +public class P2pInitiator extends P2pDevice { + + private static final String TAG = "P2pInitiator"; + + /** + * The entry point for P2P tag operations. + * @hide + */ + private IP2pInitiator mService; + + /** + * Internal constructor for the P2pInitiator class. + * + * @param handle The handle returned by the NFC service and used to identify + * the tag in subsequent calls. + * + * @hide + */ + P2pInitiator(IP2pInitiator service, int handle) { + this.mService = service; + this.mHandle = handle; + } + + /** + * Receives data from a P2pInitiator. + * + * @return data sent by the P2pInitiator. + * @throws IOException if the target has been lost or if the connection has + * been closed. + */ + public byte[] receive() throws IOException { + try { + byte[] result = mService.receive(mHandle); + if (result == null) { + throw new IOException("Tag has been lost"); + } + return result; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in receive(): ", e); + return null; + } + } + + /** + * Sends data to a P2pInitiator. + * + * @param data data to be sent to the P2pInitiator. + * @throws IOException if the target has been lost or if the connection has + * been closed. + */ + public void send(byte[] data) throws IOException { + try { + boolean isSuccess = mService.send(mHandle, data); + if (!isSuccess) { + throw new IOException("Tag has been lost"); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in send(): ", e); + } + } + + @Override + public byte[] getGeneralBytes() { + try { + return mService.getGeneralBytes(mHandle); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getGeneralBytes(): ", e); + return null; + } + } + + @Override + public int getMode() { + return P2pDevice.MODE_P2P_INITIATOR; + } + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/P2pTarget.java b/core/java/com/trustedlogic/trustednfc/android/P2pTarget.java new file mode 100644 index 0000000000000..b5e00dbe04a5d --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/P2pTarget.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : P2PTarget.java + * Original-Author : Trusted Logic S.A. (Daniel Tomas) + */ + +package com.trustedlogic.trustednfc.android; + +import java.io.IOException; + +import com.trustedlogic.trustednfc.android.internal.ErrorCodes; + +import android.os.RemoteException; +import android.util.Log; + +/** + * P2pTarget represents the target in an NFC-IP1 peer-to-peer communication. + * + * @see P2pInitiator + * @since AA02.01 + * @hide + */ +public class P2pTarget extends P2pDevice { + + private static final String TAG = "P2pTarget"; + + /** + * The entry point for P2P tag operations. + * @hide + */ + private IP2pTarget mService; + + /** + * Flag set when the object is closed and thus not usable any more. + * @hide + */ + private boolean isClosed = false; + + /** + * Flag set when the tag is connected. + * @hide + */ + private boolean isConnected = false; + + /** + * Check if tag is still opened. + * + * @return data sent by the P2pInitiator. + * @throws NfcException if accessing a closed target. + * + * @hide + */ + public void checkState() throws NfcException { + if(isClosed) { + throw new NfcException("Tag has been closed."); + } + } + + /** + * Internal constructor for the P2pTarget class. + * + * @param handle The handle returned by the NFC service and used to identify + * the tag in subsequent calls. + * + * @hide + */ + P2pTarget(IP2pTarget service, int handle) { + this.mService = service; + this.mHandle = handle; + } + + /** + * Connects to the P2pTarget. This shall be called prior to any other + * operation on the P2pTarget. + * + * @throws NfcException + */ + public void connect() throws NfcException { + // Check state + checkState(); + if (isConnected) { + throw new NfcException("Already connected"); + } + + // Perform connect + try { + int result = mService.connect(mHandle); + if (ErrorCodes.isError(result)) { + if (result == ErrorCodes.ERROR_IO) { + throw new NfcException("Failed to connect"); + } + else { + throw NfcManager.convertErrorToNfcException(result); + } + } + isConnected = true; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in connect(): ", e); + } + } + + /** + * Disconnects from the P2p Target. This must be called so that other + * targets can be discovered. It restarts the NFC discovery loop. + * + * @throws NFCException + */ + public void disconnect() throws NfcException { + checkState(); + try { + mService.disconnect(mHandle); + isConnected = true; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in disconnect(): ", e); + } + } + + /** + * Exchanges raw data with the P2pTarget. + * + * @param data data to be sent to the P2pTarget + * @return data sent in response by the P2pTarget + * @throws IOException if the target has been lost or the connection has + * been closed. + * @throws NfcException in case of failure within the stack + */ + public byte[] transceive(byte[] data) throws IOException, NfcException { + // Check state + checkState(); + + // Perform transceive + try { + byte[] response = mService.transceive(mHandle, data); + if (response == null) { + throw new IOException("Transceive failed"); + } + return response; + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in transceive(): ", e); + return null; + } + } + + /** + * Get the General bytes of the connected P2P Target + * + * @return general bytes of the connected P2P Target + * @throws IOException if the target in not in connected state + */ + public byte[] getGeneralBytes() throws IOException { + try { + if(isConnected){ + return mService.getGeneralBytes(mHandle); + }else{ + throw new IOException("Target not in connected state"); + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getGeneralBytes(): ", e); + return null; + } + } + + @Override + public int getMode() { + return P2pDevice.MODE_P2P_TARGET; + } + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/ErrorCodes.java b/core/java/com/trustedlogic/trustednfc/android/internal/ErrorCodes.java new file mode 100644 index 0000000000000..ca3b7e0a98795 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/internal/ErrorCodes.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : ErrorCodes.java + * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau) + * Created : 26-02-2010 + */ + +package com.trustedlogic.trustednfc.android.internal; + +/** + * This class defines all the error codes that can be returned by the service + * and producing an exception on the application level. These are needed since + * binders does not support exceptions. + * + * @hide + */ +public class ErrorCodes { + + public static boolean isError(int code) { + if (code < 0) { + return true; + } else { + return false; + } + } + + public static final int SUCCESS = 0; + + public static final int ERROR_IO = -1; + + public static final int ERROR_CANCELLED = -2; + + public static final int ERROR_TIMEOUT = -3; + + public static final int ERROR_BUSY = -4; + + public static final int ERROR_CONNECT = -5; + + public static final int ERROR_DISCONNECT = -5; + + public static final int ERROR_READ = -6; + + public static final int ERROR_WRITE = -7; + + public static final int ERROR_INVALID_PARAM = -8; + + public static final int ERROR_INSUFFICIENT_RESOURCES = -9; + + public static final int ERROR_SOCKET_CREATION = -10; + + public static final int ERROR_SOCKET_NOT_CONNECTED = -11; + + public static final int ERROR_BUFFER_TO_SMALL = -12; + + public static final int ERROR_SAP_USED = -13; + + public static final int ERROR_SERVICE_NAME_USED = -14; + + public static final int ERROR_SOCKET_OPTIONS = -15; + + public static final int ERROR_NFC_ON = -16; + + public static final int ERROR_NOT_INITIALIZED = -17; + + public static final int ERROR_SE_ALREADY_SELECTED = -18; + + public static final int ERROR_SE_CONNECTED = -19; + + public static final int ERROR_NO_SE_CONNECTED = -20; + + + + + + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpConnectionlessSocket.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpConnectionlessSocket.java new file mode 100644 index 0000000000000..ccfbeb4a37328 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpConnectionlessSocket.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NativeLlcpConnectionLessSocket.java + * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau) + * Created : 18-02-2010 + */ + +package com.trustedlogic.trustednfc.android.internal; + +import com.trustedlogic.trustednfc.android.LlcpPacket; + +/** + * LlcpConnectionlessSocket represents a LLCP Connectionless object to be used + * in a connectionless communication + * + * @since AA02.01 + * {@hide} + */ + +public class NativeLlcpConnectionlessSocket { + + private int mHandle; + + private int mSap; + + private int mLinkMiu; + + public NativeLlcpConnectionlessSocket(){; + } + + public NativeLlcpConnectionlessSocket(int sap){ + mSap = sap; + } + + public native boolean doSendTo(int sap, byte[] data); + + public native LlcpPacket doReceiveFrom(int linkMiu); + + public native boolean doClose(); + + public int getLinkMiu(){ + return mLinkMiu; + } + + public int getSap(){ + return mSap; + } + + public int getHandle(){ + return mHandle; + } + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpServiceSocket.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpServiceSocket.java new file mode 100644 index 0000000000000..a01f135160788 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpServiceSocket.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NativeLlcpServerSocket.java + * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau) + * Created : 18-02-2010 + */ + +package com.trustedlogic.trustednfc.android.internal; + +/** + * LlcpServiceSocket represents a LLCP Service to be used in a + * Connection-oriented communication + * {@hide} + */ + +public class NativeLlcpServiceSocket { + + private int mHandle; + + private int mLocalMiu; + + private int mLocalRw; + + private int mLocalLinearBufferLength; + + private int mSap; + + private int mTimeout; + + private String mServiceName; + + public NativeLlcpServiceSocket(){ + + } + + public NativeLlcpServiceSocket(String serviceName){ + mServiceName = serviceName; + } + + public native NativeLlcpSocket doAccept(int timeout, int miu, int rw, int linearBufferLength); + + public native boolean doClose(); + + public int getHandle(){ + return mHandle; + } + + public void setAcceptTimeout(int timeout){ + mTimeout = timeout; + } + + public int getAcceptTimeout(){ + return mTimeout; + } + + public int getRw(){ + return mLocalRw; + } + + public int getMiu(){ + return mLocalMiu; + } + + public int getLinearBufferLength(){ + return mLocalLinearBufferLength; + } +} diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpSocket.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpSocket.java new file mode 100644 index 0000000000000..077c5e0ebda06 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpSocket.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NativeLlcpClientSocket.java + * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau) + * Created : 18-02-2010 + */ + +package com.trustedlogic.trustednfc.android.internal; + +/** + * LlcpClientSocket represents a LLCP Connection-Oriented client to be used in a + * connection-oriented communication + * {@hide} + */ + +public class NativeLlcpSocket { + + private int mHandle; + + private int mSap; + + private int mLocalMiu; + + private int mLocalRw; + + private int mTimeout; + + public NativeLlcpSocket(){ + + } + + public NativeLlcpSocket(int sap, int miu, int rw){ + mSap = sap; + mLocalMiu = miu; + mLocalRw = rw; + } + + public native boolean doConnect(int nSap, int timeout); + + public native boolean doConnectBy(String sn, int timeout); + + public native boolean doClose(); + + public native boolean doSend(byte[] data); + + public native int doReceive(byte[] recvBuff); + + public native int doGetRemoteSocketMiu(); + + public native int doGetRemoteSocketRw(); + + + + public void setConnectTimeout(int timeout){ + mTimeout = timeout; + } + + public int getConnectTimeout(){ + return mTimeout; + } + + public int getSap(){ + return mSap; + } + + public int getMiu(){ + return mLocalMiu; + } + + public int getRw(){ + return mLocalRw; + } + + public int getHandle(){ + return mHandle; + } + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNdefTag.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNdefTag.java new file mode 100644 index 0000000000000..d1e64a660f706 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNdefTag.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NativeNdefTag.java + * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau) + * Created : 18-02-2010 + */ + +package com.trustedlogic.trustednfc.android.internal; + +/** + * Native interface to the NDEF tag functions + * + * {@hide} + */ +public class NativeNdefTag { + private int mHandle; + + public native byte[] doRead(); + + public native boolean doWrite(byte[] buf); +} diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcManager.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcManager.java new file mode 100644 index 0000000000000..2f5a0f09588ce --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcManager.java @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NativeNfcManager.java + * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau) + * Created : 18-02-2010 + */ + +package com.trustedlogic.trustednfc.android.internal; + +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; +import android.content.Context; +import android.content.Intent; +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +import com.trustedlogic.trustednfc.android.NfcManager; +import com.trustedlogic.trustednfc.android.NdefMessage; +import com.trustedlogic.trustednfc.android.NfcTag; + +/** + * Native interface to the NFC Manager functions {@hide} + */ +public class NativeNfcManager { + + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA = "com.trustedlogic.trustednfc.android.extra.INTERNAL_LLCP_LINK_STATE"; + + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION = "com.trustedlogic.trustednfc.android.action.INTERNAL_LLCP_LINK_STATE_CHANGED"; + + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String INTERNAL_TARGET_DESELECTED_ACTION = "com.trustedlogic.trustednfc.android.action.INTERNAL_TARGET_DESELECTED"; + + /* Native structure */ + private int mNative; + + private Context mContext; + + private Handler mNfcHandler; + + private static final String TAG = "NativeNfcManager"; + + private static final int MSG_NDEF_TAG = 0; + + private static final int MSG_CARD_EMULATION = 1; + + private static final int MSG_LLCP_LINK_ACTIVATION = 2; + + private static final int MSG_LLCP_LINK_DEACTIVATED = 3; + + private static final int MSG_TARGET_DESELECTED = 4; + + public NativeNfcManager(Context context) { + mNfcHandler = new NfcHandler(); + mContext = context; + } + + /** + * Initializes Native structure + */ + public native boolean initializeNativeStructure(); + + /** + * Initializes NFC stack. + */ + public native boolean initialize(); + + /** + * Deinitializes NFC stack. + */ + public native boolean deinitialize(); + + /** + * Enable discory for the NdefMessage and Transaction notification + */ + public native void enableDiscovery(int mode); + + /** + * Disables an NFCManager mode of operation. Allows to disable tag reader, + * peer to peer initiator or target modes. + * + * @param mode discovery mode to enable. Must be one of the provided + * NFCManager.DISCOVERY_MODE_* constants. + */ + public native void disableDiscoveryMode(int mode); + + public native int[] doGetSecureElementList(); + + public native void doSelectSecureElement(int seID); + + public native void doDeselectSecureElement(int seID); + + public native NativeP2pDevice doOpenP2pConnection(int timeout); + + public native NativeNfcTag doOpenTagConnection(int timeout); + + public native int doGetLastError(); + + public native void doSetProperties(int param, int value); + + public native void doCancel(); + + public native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap); + + public native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu, + int rw, int linearBufferLength); + + public native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw, + int linearBufferLength); + + public native boolean doCheckLlcp(); + + public native boolean doActivateLlcp(); + + private class NfcHandler extends Handler { + @Override + public void handleMessage(Message msg) { + + try { + switch (msg.what) { + case MSG_NDEF_TAG: + Log.d(TAG, "Checking for NDEF tag message"); + NativeNfcTag tag = (NativeNfcTag) msg.obj; + if (tag.doConnect()) { + if (tag.checkNDEF()) { + byte[] buff = tag.doRead(); + if (buff != null) { + NdefMessage msgNdef = new NdefMessage(buff); + if (msgNdef != null) { + /* Send broadcast ordered */ + Intent NdefMessageIntent = new Intent(); + NdefMessageIntent + .setAction(NfcManager.NDEF_TAG_DISCOVERED_ACTION); + NdefMessageIntent.putExtra(NfcManager.NDEF_MESSAGE_EXTRA, + msgNdef); + Log.d(TAG, "NDEF message found, broadcasting to applications"); + mContext.sendOrderedBroadcast(NdefMessageIntent, + android.Manifest.permission.NFC_NOTIFY); + /* Disconnect tag */ + tag.doAsyncDisconnect(); + } + } else { + Log.w(TAG, "Unable to read NDEF message (tag empty or not well formated)"); + /* Disconnect tag */ + tag.doAsyncDisconnect(); + } + } else { + Log.d(TAG, "Tag is *not* NDEF compliant"); + /* Disconnect tag */ + tag.doAsyncDisconnect(); + } + } else { + /* Disconnect tag */ + tag.doAsyncDisconnect(); + } + break; + case MSG_CARD_EMULATION: + Log.d(TAG, "Card Emulation message"); + byte[] aid = (byte[]) msg.obj; + /* Send broadcast ordered */ + Intent TransactionIntent = new Intent(); + TransactionIntent.setAction(NfcManager.TRANSACTION_DETECTED_ACTION); + TransactionIntent.putExtra(NfcManager.AID_EXTRA, aid); + Log.d(TAG, "Broadcasting Card Emulation event"); + mContext.sendOrderedBroadcast(TransactionIntent, + android.Manifest.permission.NFC_NOTIFY); + break; + + case MSG_LLCP_LINK_ACTIVATION: + NativeP2pDevice device = (NativeP2pDevice) msg.obj; + + Log.d(TAG, "LLCP Activation message"); + + if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) { + if (device.doConnect()) { + /* Check Llcp compliancy */ + if (doCheckLlcp()) { + /* Activate Llcp Link */ + if (doActivateLlcp()) { + Log.d(TAG, "Initiator Activate LLCP OK"); + /* Broadcast Intent Link LLCP activated */ + Intent LlcpLinkIntent = new Intent(); + LlcpLinkIntent + .setAction(INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION); + LlcpLinkIntent.putExtra( + INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA, + NfcManager.LLCP_LINK_STATE_ACTIVATED); + Log.d(TAG, "Broadcasting internal LLCP activation"); + mContext.sendBroadcast(LlcpLinkIntent); + } + + } else { + device.doDisconnect(); + } + + } + + } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) { + /* Check Llcp compliancy */ + if (doCheckLlcp()) { + /* Activate Llcp Link */ + if (doActivateLlcp()) { + Log.d(TAG, "Target Activate LLCP OK"); + /* Broadcast Intent Link LLCP activated */ + Intent LlcpLinkIntent = new Intent(); + LlcpLinkIntent + .setAction(INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION); + LlcpLinkIntent.putExtra(INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA, + NfcManager.LLCP_LINK_STATE_ACTIVATED); + Log.d(TAG, "Broadcasting internal LLCP activation"); + mContext.sendBroadcast(LlcpLinkIntent); + } + } + } + break; + + case MSG_LLCP_LINK_DEACTIVATED: + /* Broadcast Intent Link LLCP activated */ + Log.d(TAG, "LLCP Link Deactivated message"); + Intent LlcpLinkIntent = new Intent(); + LlcpLinkIntent.setAction(NfcManager.LLCP_LINK_STATE_CHANGED_ACTION); + LlcpLinkIntent.putExtra(NfcManager.LLCP_LINK_STATE_CHANGED_EXTRA, + NfcManager.LLCP_LINK_STATE_DEACTIVATED); + Log.d(TAG, "Broadcasting LLCP deactivation"); + mContext.sendOrderedBroadcast(LlcpLinkIntent, + android.Manifest.permission.NFC_LLCP); + break; + + case MSG_TARGET_DESELECTED: + /* Broadcast Intent Target Deselected */ + Log.d(TAG, "Target Deselected"); + Intent TargetDeselectedIntent = new Intent(); + TargetDeselectedIntent.setAction(INTERNAL_TARGET_DESELECTED_ACTION); + Log.d(TAG, "Broadcasting Intent"); + mContext.sendOrderedBroadcast(TargetDeselectedIntent, + android.Manifest.permission.NFC_LLCP); + break; + + default: + Log.e(TAG, "Unknown message received"); + break; + } + } catch (Exception e) { + // Log, don't crash! + Log.e(TAG, "Exception in NfcHandler.handleMessage:", e); + } + } + }; + + /** + * Notifies Ndef Message + */ + private void notifyNdefMessageListeners(NativeNfcTag tag) { + Message msg = mNfcHandler.obtainMessage(); + + msg.what = MSG_NDEF_TAG; + msg.obj = tag; + + mNfcHandler.sendMessage(msg); + } + + /** + * Notifies transaction + */ + private void notifyTargetDeselected() { + Message msg = mNfcHandler.obtainMessage(); + + msg.what = MSG_TARGET_DESELECTED; + + mNfcHandler.sendMessage(msg); + } + + /** + * Notifies transaction + */ + private void notifyTransactionListeners(byte[] aid) { + Message msg = mNfcHandler.obtainMessage(); + + msg.what = MSG_CARD_EMULATION; + msg.obj = aid; + + mNfcHandler.sendMessage(msg); + } + + /** + * Notifies P2P Device detected, to activate LLCP link + */ + private void notifyLlcpLinkActivation(NativeP2pDevice device) { + Message msg = mNfcHandler.obtainMessage(); + + msg.what = MSG_LLCP_LINK_ACTIVATION; + msg.obj = device; + + mNfcHandler.sendMessage(msg); + } + + /** + * Notifies P2P Device detected, to activate LLCP link + */ + private void notifyLlcpLinkDeactivated() { + Message msg = mNfcHandler.obtainMessage(); + + msg.what = MSG_LLCP_LINK_DEACTIVATED; + + mNfcHandler.sendMessage(msg); + } + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcTag.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcTag.java new file mode 100644 index 0000000000000..b92783d19bb9e --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcTag.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NativeNfcTag.java + * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau) + * Created : 18-02-2010 + */ + +package com.trustedlogic.trustednfc.android.internal; + +/** + * Native interface to the NFC tag functions + * + * {@hide} + */ +public class NativeNfcTag { + private int mHandle; + + private String mType; + + private byte[] mUid; + + public native boolean doConnect(); + + public native boolean doDisconnect(); + + public native void doAsyncDisconnect(); + + public native byte[] doTransceive(byte[] data); + + public native boolean checkNDEF(); + + public native byte[] doRead(); + + public native boolean doWrite(byte[] buf); + + public int getHandle() { + return mHandle; + } + + public String getType() { + return mType; + } + + public byte[] getUid() { + return mUid; + } +} diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeP2pDevice.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeP2pDevice.java new file mode 100644 index 0000000000000..75d25bad023a4 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeP2pDevice.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * File : NativeP2pDevice.java + * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau) + * Created : 18-02-2010 + */ + +package com.trustedlogic.trustednfc.android.internal; + +/** + * Native interface to the P2P Initiator functions + * + * {@hide} + */ +public class NativeP2pDevice { + + /** + * Peer-to-Peer Target. + */ + public static final short MODE_P2P_TARGET = 0x00; + + /** + * Peer-to-Peer Initiator. + */ + public static final short MODE_P2P_INITIATOR = 0x01; + + /** + * Invalid target type. + */ + public static final short MODE_INVALID = 0xff; + + private int mHandle; + + private int mMode; + + private byte[] mGeneralBytes; + + public native byte[] doReceive(); + + public native boolean doSend(byte[] data); + + public native boolean doConnect(); + + public native boolean doDisconnect(); + + public native byte[] doTransceive(byte[] data); + + public int getHandle() { + return mHandle; + } + + public int getMode() { + return mMode; + } + + public byte[] getGeneralBytes() { + return mGeneralBytes; + } + +} diff --git a/core/java/com/trustedlogic/trustednfc/android/package.html b/core/java/com/trustedlogic/trustednfc/android/package.html new file mode 100644 index 0000000000000..0c0b6059738d3 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/package.html @@ -0,0 +1,473 @@ + + + +

Provides classes that manage the NFC functionality.

+ +

The NFC functionality is related to Near Field Communication.

+ +

The NFC APIs let applications:

+
    +
  • Scan for remote NFC targets (NFC Tag or NFC Peer)
  • +
  • Transfer raw data to and from remote NFC targets (NFC Tags or NFC Peer)
  • +
  • Read/Write NDEF data from/to remote NFC targets (NFC Tags)
  • +
  • Establish LLCP connection with a remote NFC target (NFC Peer with LLCP support)
  • +
  • Exchange data with a remote NFC target through LLCP services (NFC Peer with LLCP support)
  • +
  • Be notified of transactions on the local Secure Element by an external NFC reader
  • +
+ + +

Setting Up NFC

+ +

+Before an application can use the NFC feature, it needs to check if NFC is +supported on the device by getting an instance of the +{@link com.trustedlogic.trustednfc.android.NfcManager} class. +

+ +
+	NfcManager mNfcManager = (NfcManager) getSystemService(Context.NFC_SERVICE);
+	if (mNfcManager == null) {
+		// Device does not support NFC
+	}
+
+ +

+An application can ensure that NFC is enabled. +If not, an application with the needed permission can request that NFC be +enabled. +

+ +
+	if (!mNfcManager.isEnabled) {
+		// NFC is currently disabled.
+		// Enable NFC.
+		mNfcManager.enable();
+	}
+
+ +

+Before using the card emulation mode, an application can ensure that a secure +element is selected ({@link com.trustedlogic.trustednfc.android.NfcManager#getSelectedSecureElement}). +If not, an application with the needed permission can recover the list of +available secure elements on the device +({@link com.trustedlogic.trustednfc.android.NfcManager#getSecureElementList}) and select one +({@link com.trustedlogic.trustednfc.android.NfcManager#selectSecureElement}). +

+ +

+Before using the NFC feature, an application can configure the NFC device by +calling {@link com.trustedlogic.trustednfc.android.NfcManager#setProperties}. This function allows: +

+
    +
  • Enabling/disabling the NFC device capabilities (RF types, baudrates, + NFCIP-1 mode and role...)
  • +
  • Settings the NFCIP-1 general bytes and the LLCP link parameters
  • +
+

+The setting properties can be customized according to the Device capabilities. +The next table give the minimal set of properties supported by the Device. +Depending on the implementation, the table may be completed. +

+ + + + + + + + + + + + + + + +
Property Name Property Values
discovery.felica true|false
discovery.iso14443A true|false
discovery.iso14443B true|false
discovery.iso15693 true|false
discovery.nfcip true|false
nfcip.baudrate 106|212|424
nfcip.generalbytes
nfcip.mode active|passive|all
nfcip.role initiator|target|both
llcp.lto 150 (0 to 255)
llcp.opt 0 (0 to 3)
llcp.miu 128 (128 to 2176)
llcp.wks 1 (0 to 15)
+

(default values in bold)

+ + +

NFC Permissions

+ +

+To change the NFC service settings such as enabling the NFC targets +discovery or activating the secure element, an application must declare the +NFC_ADMIN permission. +

+

+To perform NFC raw communication with a remote NFC target in +Reader/Write Mode or Peer-to-Peer Mode, an application must declare the NFC_RAW +permission. +

+

+To receive NDEF message or Secure Element intents, an application must declare +the NFC_NOTIFY permission. +

+

+To receive the LLCP link intent and perform an LLCP communication with a remote NFC target, an application must +declare the NFC_LLCP permission. +

+ + +

NFC Usage

+ +

+The following code samples illustrate the APIs usage regarding the NFC service +use cases. +

+ +

Reader/Writer Mode NDEF message notification

+ +

+This code sample illustrates the NDEF message notification through an Intent declared in the manifest and a receiver implemented in the application. +

+

Main involved classes/methods:

+ +

Manifest Example:

+
+	<receiver android:name=".NfcReaderDemoReceiver">
+            <intent-filter>
+               <action android:name= "com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED"/>
+            </intent-filter>
+        </receiver>
+
+ +

Receiver Example:

+
    +
  • {@link com.trustedlogic.trustednfc.android.NdefMessage}
  • +
  • {@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_TAG_DISCOVERED_ACTION}
  • +
  • {@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_MESSAGE_EXTRA}
  • +
+
+public class NdefMessageReceiverSample extends BroadcastReceiver {
+	public void onReceive(Context context, Intent intent) {
+		if (intent.getAction().equals(NfcManager.NDEF_TAG_DISCOVERERD_ACTION)) {
+			NdefMessage msg = intent.getParcelableExtra(NfcManager.NDEF_MESSAGE_EXTRA);
+		
+		/* Manage the NdefMessage received */
+	}
+
+ +

Reader/Writer Mode raw exchange

+ +

+This code sample illustrates raw exchanges with a NFC target in Reader/Writer +mode. +

+

Main involved classes/methods:

+
    +
  • {@link com.trustedlogic.trustednfc.android.NfcManager#openTagConnection}
  • +
  • {@link com.trustedlogic.trustednfc.android.NfcTag}
  • +
+ +
+public class TagReaderSample {
+
+	/** The NFC manager to access NFC features */
+	private NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
+
+	private void runTagReader() {
+		NfcTag tag = null;
+		String type;
+		byte[] cmd = { 0x01, 0x02, 0x03 };
+		byte[] res;
+
+		while (true) {
+			try {
+				Log.i("NFC example", "Please wave in front of the tag");
+				// Open a connection on next available tag
+				try {
+					tag = manager.openTagConnection();
+				} catch (NfcException e) {
+					// TODO: Handle open failure
+				}
+
+				// Look for a mifare 4k
+				type = tag.getType();
+				if (type.equals("Mifare4K")) {
+					Log.i("NFC example", "Tag detected");
+					tag.connect();
+					// Ready to communicate, we can send transceive !
+					res = tag.transceive(cmd);
+				} else {
+					Log.i("NFC example", "Unknown tag");
+				}
+			} catch (IOException e) {
+				// TODO: Handle broken connection
+			} finally {
+				if (tag != null) {
+					tag.close();
+				}
+			}
+		}
+	}
+}
+
+ +

Peer-to-Peer Mode raw exchange

+ +

+This code sample illustrates raw exchanges with a NFC target in Peer-to-Peer +mode. +

+

Main involved classes/methods:

+
    +
  • {@link com.trustedlogic.trustednfc.android.NfcManager#openP2pConnection}
  • +
  • {@link com.trustedlogic.trustednfc.android.P2pDevice}
  • +
  • {@link com.trustedlogic.trustednfc.android.P2pInitiator}
  • +
  • {@link com.trustedlogic.trustednfc.android.P2pTarget}
  • +
+ +
+public class P2pSample {
+
+	/** The NFC manager to access NFC features */
+	private NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
+
+	private void runP2p() {
+		P2pDevice deviceP2p;
+		P2pInitiator initiator;
+		P2pTarget target;
+		byte[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+		byte[] echo = new byte[data.length * 10];
+
+		try {
+			deviceP2p = manager.openP2pConnection();
+
+			if (deviceP2p.getMode() == P2pDevice.MODE_P2P_INITIATOR) {
+				target = new P2pTarget(deviceP2p);
+				// Connect to the detected P2P target
+				target.connect();
+				// send data to the target
+				target.transceive(data);
+				// disconnect the connected target
+				target.disconnect();
+			} else if (deviceP2p.getMode() == P2pDevice.MODE_P2P_TARGET) {
+				initiator = new P2pInitiator(deviceP2p);
+				//target in receive state 
+				echo = initiator.receive();	
+				// send back the data received
+				initiator.send(echo);
+			}
+		} catch (IOException e0) {
+
+		} catch (NfcException e1) {
+
+		}
+	}
+}
+
+ +

Peer-to-Peer Mode LLCP exchange

+ +

+This code sample illustrates how to get LLCP link state notification with the declaration of a Receiver in the manifest of the application and the implementation +of the receiver in the application. +

+

Manifest Example:

+
+	<receiver android:name=".LlcpModeReceiverSample">
+            <intent-filter>
+		<action android:name= "com.trustedlogic.trustednfc.android.action.LLCP_LINK_STATE_CHANGED"/>
+            </intent-filter>
+        </receiver>
+
+ +

Receiver Example:

+
    +
  • {@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_ACTION}
  • +
  • {@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_EXTRA}
  • +
+
+public class LlcpModeReceiverSample extends BroadcastReceiver {
+	public void onReceive(Context context, Intent intent) {
+
+		if (intent.getAction().equals(NfcManager.LLCP_LINK_STATE_CHANGED_ACTION)){
+			byte[] aid = intent.getByteArrayExtra(NfcManager.LLCP_LINK_STATE_CHANGED_EXTRA);
+			/* Create an LLCP service or client and start an LLCP communication */
+		} 
+	}
+
+ + +

+This code samples illustrate LLCP exchanges with a NFC Peer. +

+

Main involved classes/methods:

+
    +
  • {@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpSocket}
  • +
  • {@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpConnectionlessSocket}
  • +
  • {@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpServiceSocket}
  • +
  • {@link com.trustedlogic.trustednfc.android.LlcpSocket}
  • +
  • {@link com.trustedlogic.trustednfc.android.LlcpConnectionlessSocket}
  • +
  • {@link com.trustedlogic.trustednfc.android.LlcpPacket}
  • +
  • {@link com.trustedlogic.trustednfc.android.LlcpServiceSocket}
  • +
+ +
+public class LlcpServerSample {
+
+	/** The NFC manager to access NFC features */
+	private NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
+
+	private void runLlcpClient() {
+		LlcpSocket sock;
+		byte[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+		byte[] echo = new byte[data.length * 10];
+		int length = 0;
+
+		sock = manager.createLlcpSocket((short) 128, (byte) 2, 1024);
+		
+		// set a timeout in ms for connect request
+		sock.setConnectTimeout(10);
+		
+		try {
+			// Connect to remote service
+			// NOTE: could be sock.connect("com.trusted-logic.tnfc.testapp");
+			sock.connect((byte) 0x10);
+
+			// Send data
+			for (int i = 0; i < 10; i++) {
+				sock.send(data);
+			}
+
+			// Receive echo
+			while (length < 10 * data.length) {
+				length += sock.receive(echo);
+			}
+
+		} catch (IOException e) {
+			// TODO: Handle broken connection broken (link down, remote closure
+			// or connect rejected) or Timeout expired
+		}
+	}
+}
+
+ +
+public class LlcpClientSample {
+
+	/** The NFC manager to access NFC features */
+	private NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
+
+	private void runLlcpClient() {
+		LlcpSocket sock;
+		byte[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+		byte[] echo = new byte[data.length * 10];
+		int length = 0;
+
+		sock = manager.createLlcpSocket((short) 128, (byte) 2, 1024);
+		try {
+			// Connect to remote service
+			// NOTE: could be sock.connect("com.trusted-logic.tnfc.testapp");
+			sock.connect((byte) 0x10);
+
+			// Send data
+			for (int i = 0; i < 10; i++) {
+				sock.send(data);
+			}
+
+			// Receive echo
+			while (length < 10 * data.length) {
+				length += sock.receive(echo);
+			}
+
+		} catch (IOException e) {
+			// TODO: Handle broken connection broken (link down, remote closure
+			// or connect rejected)
+		}
+	}
+}
+
+ +

Card Emulation Mode transaction notification

+ +

+This code sample illustrates how to get the card emulation notification with the declaration of a Receiver in the manifest of the application and the implementation +of the receiver in the application. +

+

Manifest Example:

+
+	<receiver android:name=".NfcReaderDemoReceiver">
+            <intent-filter>
+		<action android:name= "com.trustedlogic.trustednfc.android.action.TRANSACTION_DETECTED"/>
+            </intent-filter>
+        </receiver>
+
+ +

Receiver Example:

+
    +
  • {@link com.trustedlogic.trustednfc.android.NfcManager#TRANSACTION_DETECTED_ACTION}
  • +
  • {@link com.trustedlogic.trustednfc.android.NfcManager#AID_EXTRA}
  • +
+
+public class CardEmulationReceiverSample extends BroadcastReceiver {
+	public void onReceive(Context context, Intent intent) {
+
+		if (intent.getAction().equals(NfcManager.TRANSACTION_DETECTED_ACTION)){
+			byte[] aid = intent.getByteArrayExtra(NfcManager.AID_EXTRA);
+			/* Manage the AID: */
+			/* For example start an activity related to this AID value or display a popup with the AID */
+		} 
+	}
+
+ + + +

Multiple Applications rules

+ +

+Several LLCP sockets can be created by a single application or by multiple +applications by calling {@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpSocket}, +{@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpConnectionlessSocket} or +{@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpServiceSocket}, provided the local SAP +numbers are differents. +

+ +

+Only one application can open a raw connection by calling +{@link com.trustedlogic.trustednfc.android.NfcManager#openTagConnection} or +{@link com.trustedlogic.trustednfc.android.NfcManager#openP2pConnection}. +While this application has not closed or cancelled its connection, any other +application that attempts to open another raw connection will raise an +exception. +During an open connnection, the card emulation mode is always enabled and +applications are able to receive card emulation intents. +

+ +

+When an application opens a tag connection by calling +{@link com.trustedlogic.trustednfc.android.NfcManager#openTagConnection}, this operation is exclusive, no NDEF message intent are +broadcast while the connection is not closed or canceled. +

+ +

+When an application opens a peer-to-peer connection by calling +{@link com.trustedlogic.trustednfc.android.NfcManager#openP2pConnection}, this operation is exclusive, no LLCP intent are broadcast and LLCP sockets are +disabled while the connection is not closed or canceled. +

+ + +

NFC Tag types

+ +

+The {@link com.trustedlogic.trustednfc.android.NfcTag} type returned by +{@link com.trustedlogic.trustednfc.android.NfcTag#getType} indicates the set of +commands supported by the tag. These commands can be used in +{@link com.trustedlogic.trustednfc.android.NfcTag#transceive}. +

+ + + + + + + + + + + +
Tag Type Returned string
Jewel/Topaz Jewel
Mifare UltraLight MifareUL
Mifare Standard 1K Mifare1K
Mifare Standard 4K Mifare4K
Mifare DESFIRE MifareDESFIRE
Felica Felica
ISO14443-4 A or B Iso14443
ISO15693 Iso15693
+ + + diff --git a/core/jni/Android.mk b/core/jni/Android.mk index fffd1856330dc..64a23315ad6ec 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -202,6 +202,14 @@ ifeq ($(USE_OPENGL_RENDERER),true) LOCAL_SHARED_LIBRARIES += libhwui endif +ifeq ($(BOARD_HAVE_NFC),true) +LOCAL_SHARED_LIBRARIES += \ + libnfc_jni \ + libnfc + +LOCAL_CFLAGS += -DHAVE_NFC +endif + ifeq ($(BOARD_HAVE_BLUETOOTH),true) LOCAL_C_INCLUDES += \ external/dbus \ diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index ff62e0db52981..a4a1a700e82b1 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -170,6 +170,18 @@ extern int register_android_view_MotionEvent(JNIEnv* env); extern int register_android_content_res_ObbScanner(JNIEnv* env); extern int register_android_content_res_Configuration(JNIEnv* env); +#ifdef HAVE_NFC +extern int register_com_trustedlogic_trustednfc_android_internal_NativeNfcManager(JNIEnv *env); +extern int register_com_trustedlogic_trustednfc_android_internal_NativeNfcTag(JNIEnv *env); +extern int register_com_trustedlogic_trustednfc_android_internal_NativeNdefTag(JNIEnv *env); +extern int register_com_trustedlogic_trustednfc_android_NdefMessage(JNIEnv *env); +extern int register_com_trustedlogic_trustednfc_android_NdefRecord(JNIEnv *env); +extern int register_com_trustedlogic_trustednfc_android_internal_NativeP2pDevice(JNIEnv *env); +extern int register_com_trustedlogic_trustednfc_android_internal_NativeLlcpSocket(JNIEnv *env); +extern int register_com_trustedlogic_trustednfc_android_internal_NativeLlcpConnectionlessSocket(JNIEnv *env); +extern int register_com_trustedlogic_trustednfc_android_internal_NativeLlcpServiceSocket(JNIEnv *env); +#endif + static AndroidRuntime* gCurRuntime = NULL; static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL) @@ -1287,6 +1299,18 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_content_res_ObbScanner), REG_JNI(register_android_content_res_Configuration), + +#ifdef HAVE_NFC + REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeNfcManager), + REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeNfcTag), + REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeNdefTag), + REG_JNI(register_com_trustedlogic_trustednfc_android_NdefMessage), + REG_JNI(register_com_trustedlogic_trustednfc_android_NdefRecord), + REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeP2pDevice), + REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeLlcpSocket), + REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeLlcpConnectionlessSocket), + REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeLlcpServiceSocket), +#endif }; /* diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index d5065f6d5a770..3a1d76f861670 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -88,6 +88,10 @@ + + + + @@ -338,6 +342,30 @@ android:description="@string/permdesc_bluetooth" android:label="@string/permlab_bluetooth" /> + + + + + + + + + + + + + + NFC administration + + Allows an application to configure + the local NFC phone. + + + NFC full access to remote device + + Allows an application to access + remote NFC devices. + + + NFC notification from remote device + + Allows an application to be notified + of operations related to remote NFC devices. + + + NFC notification from remote LLCP device + + Allows an application to be notified + of LLCP operations related to remote NFC devices. + disable keylock diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 7db6710a47800..717f63cc7131c 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -19,6 +19,7 @@ package com.android.server; import com.android.server.am.ActivityManagerService; import com.android.internal.os.BinderInternal; import com.android.internal.os.SamplingProfilerIntegration; +import com.trustedlogic.trustednfc.android.server.NfcService; import dalvik.system.VMRuntime; import dalvik.system.Zygote; @@ -44,6 +45,7 @@ import android.server.BluetoothA2dpService; import android.server.BluetoothService; import android.server.search.SearchManagerService; import android.util.EventLog; +import android.util.Log; import android.util.Slog; import java.io.File; @@ -413,6 +415,20 @@ class ServerThread extends Thread { } catch (Throwable e) { Slog.e(TAG, "Failure starting Recognition Service", e); } + + try { + Slog.i(TAG, "Nfc Service"); + NfcService nfc; + try { + nfc = new NfcService(context); + } catch (UnsatisfiedLinkError e) { // gross hack to detect NFC + nfc = null; + Slog.w(TAG, "No NFC support"); + } + ServiceManager.addService(Context.NFC_SERVICE, nfc); + } catch (Throwable e) { + Slog.e(TAG, "Failure starting NFC Service", e); + } try { Slog.i(TAG, "DiskStats Service"); diff --git a/services/java/com/trustedlogic/trustednfc/android/server/NfcService.java b/services/java/com/trustedlogic/trustednfc/android/server/NfcService.java new file mode 100644 index 0000000000000..431b798ee28ca --- /dev/null +++ b/services/java/com/trustedlogic/trustednfc/android/server/NfcService.java @@ -0,0 +1,2111 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.trustedlogic.trustednfc.android.server; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.ListIterator; +import java.util.Set; + +import com.trustedlogic.trustednfc.android.ILlcpConnectionlessSocket; +import com.trustedlogic.trustednfc.android.ILlcpServiceSocket; +import com.trustedlogic.trustednfc.android.INfcManager; +import com.trustedlogic.trustednfc.android.ILlcpSocket; +import com.trustedlogic.trustednfc.android.INfcTag; +import com.trustedlogic.trustednfc.android.IP2pInitiator; +import com.trustedlogic.trustednfc.android.IP2pTarget; +import com.trustedlogic.trustednfc.android.LlcpPacket; +import com.trustedlogic.trustednfc.android.NdefMessage; +import com.trustedlogic.trustednfc.android.NfcException; +import com.trustedlogic.trustednfc.android.NfcManager; +import com.trustedlogic.trustednfc.android.internal.NativeLlcpConnectionlessSocket; +import com.trustedlogic.trustednfc.android.internal.NativeLlcpServiceSocket; +import com.trustedlogic.trustednfc.android.internal.NativeLlcpSocket; +import com.trustedlogic.trustednfc.android.internal.NativeNfcManager; +import com.trustedlogic.trustednfc.android.internal.NativeNfcTag; +import com.trustedlogic.trustednfc.android.internal.NativeP2pDevice; +import com.trustedlogic.trustednfc.android.internal.ErrorCodes; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.Process; +import android.os.RemoteException; +import android.provider.Settings; +import android.provider.Settings.SettingNotFoundException; +import android.util.Log; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; + +public class NfcService extends INfcManager.Stub implements Runnable { + + /** + * NFC Service tag + */ + private static final String TAG = "NfcService"; + + /** + * NFC features disabled state + */ + private static final short NFC_STATE_DISABLED = 0x00; + + /** + * NFC features enabled state + */ + private static final short NFC_STATE_ENABLED = 0x01; + + /** + * NFC Discovery for Reader mode + */ + private static final int DISCOVERY_MODE_READER = 0; + + /** + * NFC Discovery for Card Emulation Mode + */ + private static final int DISCOVERY_MODE_CARD_EMULATION = 2; + + /** + * LLCP Service Socket type + */ + private static final int LLCP_SERVICE_SOCKET_TYPE = 0; + + /** + * LLCP Socket type + */ + private static final int LLCP_SOCKET_TYPE = 1; + + /** + * LLCP Connectionless socket type + */ + private static final int LLCP_CONNECTIONLESS_SOCKET_TYPE = 2; + + /** + * Maximun number of sockets managed + */ + private static final int LLCP_SOCKET_NB_MAX = 5; + + /** + * Default value for the Maximum Information Unit parameter + */ + private static final int LLCP_LTO_DEFAULT_VALUE = 150; + + /** + * Default value for the Maximum Information Unit parameter + */ + private static final int LLCP_LTO_MAX_VALUE = 255; + + /** + * Maximun value for the Receive Window + */ + private static final int LLCP_RW_MAX_VALUE = 15; + + /** + * Default value for the Maximum Information Unit parameter + */ + private static final int LLCP_MIU_DEFAULT_VALUE = 128; + + /** + * Default value for the Maximum Information Unit parameter + */ + private static final int LLCP_MIU_MAX_VALUE = 2176; + + /** + * Default value for the Well Known Service List parameter + */ + private static final int LLCP_WKS_DEFAULT_VALUE = 1; + + /** + * Max value for the Well Known Service List parameter + */ + private static final int LLCP_WKS_MAX_VALUE = 15; + + /** + * Default value for the Option parameter + */ + private static final int LLCP_OPT_DEFAULT_VALUE = 0; + + /** + * Max value for the Option parameter + */ + private static final int LLCP_OPT_MAX_VALUE = 3; + + /** + * LLCP Properties + */ + private static final int PROPERTY_LLCP_LTO = 0; + + private static final int PROPERTY_LLCP_MIU = 1; + + private static final int PROPERTY_LLCP_WKS = 2; + + private static final int PROPERTY_LLCP_OPT = 3; + + private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto"; + + private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu"; + + private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks"; + + private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt"; + + /** + * NFC Reader Properties + */ + private static final int PROPERTY_NFC_DISCOVERY_A = 4; + + private static final int PROPERTY_NFC_DISCOVERY_B = 5; + + private static final int PROPERTY_NFC_DISCOVERY_F = 6; + + private static final int PROPERTY_NFC_DISCOVERY_15693 = 7; + + private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8; + + private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A"; + + private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B"; + + private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica"; + + private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693"; + + private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip"; + + private Context mContext; + + private HashMap mObjectMap = new HashMap(); + + private HashMap mSocketMap = new HashMap(); + + private LinkedList mRegisteredSocketList = new LinkedList(); + + private int mLlcpLinkState = NfcManager.LLCP_LINK_STATE_DEACTIVATED; + + private int mGeneratedSocketHandle = 0; + + private int mNbSocketCreated = 0; + + private boolean mIsNfcEnabled = false; + + private NfcHandler mNfcHandler; + + private int mSelectedSeId = 0; + + private int mTimeout = 0; + + private int mNfcState; + + private int mNfcSecureElementState; + + private boolean mOpenPending = false; + + private NativeNfcManager mManager; + + private ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() { + + public int close(int nativeHandle) throws RemoteException { + NativeLlcpSocket socket = null; + boolean isSuccess = false; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) { + isSuccess = socket.doClose(); + if (isSuccess) { + /* Remove the socket closed from the hmap */ + RemoveSocket(nativeHandle); + /* Update mNbSocketCreated */ + mNbSocketCreated--; + return ErrorCodes.SUCCESS; + } else { + return ErrorCodes.ERROR_IO; + } + } else { + /* Remove the socket closed from the hmap */ + RemoveSocket(nativeHandle); + + /* Remove registered socket from the list */ + RemoveRegisteredSocket(nativeHandle); + + /* Update mNbSocketCreated */ + mNbSocketCreated--; + + return ErrorCodes.SUCCESS; + } + } else { + return ErrorCodes.ERROR_IO; + } + } + + public int connect(int nativeHandle, int sap) throws RemoteException { + NativeLlcpSocket socket = null; + boolean isSuccess = false; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + isSuccess = socket.doConnect(sap, socket.getConnectTimeout()); + if (isSuccess) { + return ErrorCodes.SUCCESS; + } else { + return ErrorCodes.ERROR_IO; + } + } else { + return ErrorCodes.ERROR_IO; + } + + } + + public int connectByName(int nativeHandle, String sn) throws RemoteException { + NativeLlcpSocket socket = null; + boolean isSuccess = false; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + isSuccess = socket.doConnectBy(sn, socket.getConnectTimeout()); + if (isSuccess) { + return ErrorCodes.SUCCESS; + } else { + return ErrorCodes.ERROR_IO; + } + } else { + return ErrorCodes.ERROR_IO; + } + + } + + public int getConnectTimeout(int nativeHandle) throws RemoteException { + NativeLlcpSocket socket = null; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + return socket.getConnectTimeout(); + } else { + return 0; + } + } + + public int getLocalSap(int nativeHandle) throws RemoteException { + NativeLlcpSocket socket = null; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + return socket.getSap(); + } else { + return 0; + } + } + + public int getLocalSocketMiu(int nativeHandle) throws RemoteException { + NativeLlcpSocket socket = null; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + return socket.getMiu(); + } else { + return 0; + } + } + + public int getLocalSocketRw(int nativeHandle) throws RemoteException { + NativeLlcpSocket socket = null; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + return socket.getRw(); + } else { + return 0; + } + } + + public int getRemoteSocketMiu(int nativeHandle) throws RemoteException { + NativeLlcpSocket socket = null; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + if (socket.doGetRemoteSocketMiu() != 0) { + return socket.doGetRemoteSocketMiu(); + } else { + return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; + } + } else { + return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; + } + } + + public int getRemoteSocketRw(int nativeHandle) throws RemoteException { + NativeLlcpSocket socket = null; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + if (socket.doGetRemoteSocketRw() != 0) { + return socket.doGetRemoteSocketRw(); + } else { + return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; + } + } else { + return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED; + } + } + + public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException { + NativeLlcpSocket socket = null; + int receiveLength = 0; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + receiveLength = socket.doReceive(receiveBuffer); + if (receiveLength != 0) { + return receiveLength; + } else { + return ErrorCodes.ERROR_IO; + } + } else { + return ErrorCodes.ERROR_IO; + } + } + + public int send(int nativeHandle, byte[] data) throws RemoteException { + NativeLlcpSocket socket = null; + boolean isSuccess = false; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + isSuccess = socket.doSend(data); + if (isSuccess) { + return ErrorCodes.SUCCESS; + } else { + return ErrorCodes.ERROR_IO; + } + } else { + return ErrorCodes.ERROR_IO; + } + } + + public void setConnectTimeout(int nativeHandle, int timeout) throws RemoteException { + NativeLlcpSocket socket = null; + + /* find the socket in the hmap */ + socket = (NativeLlcpSocket) findSocket(nativeHandle); + if (socket != null) { + socket.setConnectTimeout(timeout); + } + } + + }; + + private ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() { + + public int accept(int nativeHandle) throws RemoteException { + NativeLlcpServiceSocket socket = null; + NativeLlcpSocket clientSocket = null; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { + /* find the socket in the hmap */ + socket = (NativeLlcpServiceSocket) findSocket(nativeHandle); + if (socket != null) { + clientSocket = socket.doAccept(socket.getAcceptTimeout(), socket.getMiu(), + socket.getRw(), socket.getLinearBufferLength()); + if (clientSocket != null) { + /* Add the socket into the socket map */ + mSocketMap.put(clientSocket.getHandle(), clientSocket); + mNbSocketCreated++; + return clientSocket.getHandle(); + } else { + return ErrorCodes.ERROR_IO; + } + } else { + return ErrorCodes.ERROR_IO; + } + } else { + return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; + } + + } + + public void close(int nativeHandle) throws RemoteException { + NativeLlcpServiceSocket socket = null; + boolean isSuccess = false; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpServiceSocket) findSocket(nativeHandle); + if (socket != null) { + if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) { + isSuccess = socket.doClose(); + if (isSuccess) { + /* Remove the socket closed from the hmap */ + RemoveSocket(nativeHandle); + /* Update mNbSocketCreated */ + mNbSocketCreated--; + } + } else { + /* Remove the socket closed from the hmap */ + RemoveSocket(nativeHandle); + + /* Remove registered socket from the list */ + RemoveRegisteredSocket(nativeHandle); + + /* Update mNbSocketCreated */ + mNbSocketCreated--; + } + } + } + + public int getAcceptTimeout(int nativeHandle) throws RemoteException { + NativeLlcpServiceSocket socket = null; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpServiceSocket) findSocket(nativeHandle); + if (socket != null) { + return socket.getAcceptTimeout(); + } else { + return 0; + } + } + + public void setAcceptTimeout(int nativeHandle, int timeout) throws RemoteException { + NativeLlcpServiceSocket socket = null; + + /* find the socket in the hmap */ + socket = (NativeLlcpServiceSocket) findSocket(nativeHandle); + if (socket != null) { + socket.setAcceptTimeout(timeout); + } + } + }; + + private ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() { + + public void close(int nativeHandle) throws RemoteException { + NativeLlcpConnectionlessSocket socket = null; + boolean isSuccess = false; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); + if (socket != null) { + if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) { + isSuccess = socket.doClose(); + if (isSuccess) { + /* Remove the socket closed from the hmap */ + RemoveSocket(nativeHandle); + /* Update mNbSocketCreated */ + mNbSocketCreated--; + } + } else { + /* Remove the socket closed from the hmap */ + RemoveSocket(nativeHandle); + + /* Remove registered socket from the list */ + RemoveRegisteredSocket(nativeHandle); + + /* Update mNbSocketCreated */ + mNbSocketCreated--; + } + } + } + + public int getSap(int nativeHandle) throws RemoteException { + NativeLlcpConnectionlessSocket socket = null; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); + if (socket != null) { + return socket.getSap(); + } else { + return 0; + } + } + + public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException { + NativeLlcpConnectionlessSocket socket = null; + LlcpPacket packet; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return null; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); + if (socket != null) { + packet = socket.doReceiveFrom(socket.getLinkMiu()); + if (packet != null) { + return packet; + } + return null; + } else { + return null; + } + } + + public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException { + NativeLlcpConnectionlessSocket socket = null; + boolean isSuccess = false; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the socket in the hmap */ + socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle); + if (socket != null) { + isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer()); + if (isSuccess) { + return ErrorCodes.SUCCESS; + } else { + return ErrorCodes.ERROR_IO; + } + } else { + return ErrorCodes.ERROR_IO; + } + } + }; + + private INfcTag mNfcTagService = new INfcTag.Stub() { + + public int close(int nativeHandle) throws RemoteException { + NativeNfcTag tag = null; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the tag in the hmap */ + tag = (NativeNfcTag) findObject(nativeHandle); + if (tag != null) { + if (tag.doDisconnect()) { + /* Remove the device from the hmap */ + RemoveObject(nativeHandle); + /* Restart polling loop for notification */ + mManager.enableDiscovery(DISCOVERY_MODE_READER); + mOpenPending = false; + return ErrorCodes.SUCCESS; + } + + } + /* Restart polling loop for notification */ + mManager.enableDiscovery(DISCOVERY_MODE_READER); + mOpenPending = false; + return ErrorCodes.ERROR_DISCONNECT; + } + + public int connect(int nativeHandle) throws RemoteException { + NativeNfcTag tag = null; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the tag in the hmap */ + tag = (NativeNfcTag) findObject(nativeHandle); + if (tag != null) { + if (tag.doConnect()) + return ErrorCodes.SUCCESS; + } + /* Restart polling loop for notification */ + mManager.enableDiscovery(DISCOVERY_MODE_READER); + mOpenPending = false; + return ErrorCodes.ERROR_CONNECT; + } + + public String getType(int nativeHandle) throws RemoteException { + NativeNfcTag tag = null; + String type; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return null; + } + + /* find the tag in the hmap */ + tag = (NativeNfcTag) findObject(nativeHandle); + if (tag != null) { + type = tag.getType(); + return type; + } + return null; + } + + public byte[] getUid(int nativeHandle) throws RemoteException { + NativeNfcTag tag = null; + byte[] uid; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return null; + } + + /* find the tag in the hmap */ + tag = (NativeNfcTag) findObject(nativeHandle); + if (tag != null) { + uid = tag.getUid(); + return uid; + } + return null; + } + + public boolean isNdef(int nativeHandle) throws RemoteException { + NativeNfcTag tag = null; + boolean isSuccess = false; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return isSuccess; + } + + /* find the tag in the hmap */ + tag = (NativeNfcTag) findObject(nativeHandle); + if (tag != null) { + isSuccess = tag.checkNDEF(); + } + return isSuccess; + } + + public byte[] transceive(int nativeHandle, byte[] data) throws RemoteException { + NativeNfcTag tag = null; + byte[] response; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return null; + } + + /* find the tag in the hmap */ + tag = (NativeNfcTag) findObject(nativeHandle); + if (tag != null) { + response = tag.doTransceive(data); + return response; + } + return null; + } + + public NdefMessage read(int nativeHandle) throws RemoteException { + NativeNfcTag tag; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return null; + } + + /* find the tag in the hmap */ + tag = (NativeNfcTag) findObject(nativeHandle); + if (tag != null) { + byte[] buf = tag.doRead(); + if (buf == null) + return null; + + /* Create an NdefMessage */ + try { + return new NdefMessage(buf); + } catch (NfcException e) { + return null; + } + } + return null; + } + + public boolean write(int nativeHandle, NdefMessage msg) throws RemoteException { + NativeNfcTag tag; + boolean isSuccess = false; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return isSuccess; + } + + /* find the tag in the hmap */ + tag = (NativeNfcTag) findObject(nativeHandle); + if (tag != null) { + isSuccess = tag.doWrite(msg.toByteArray()); + } + return isSuccess; + + } + + }; + + private IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() { + + public byte[] getGeneralBytes(int nativeHandle) throws RemoteException { + NativeP2pDevice device; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return null; + } + + /* find the device in the hmap */ + device = (NativeP2pDevice) findObject(nativeHandle); + if (device != null) { + byte[] buff = device.getGeneralBytes(); + if (buff == null) + return null; + return buff; + } + return null; + } + + public int getMode(int nativeHandle) throws RemoteException { + NativeP2pDevice device; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the device in the hmap */ + device = (NativeP2pDevice) findObject(nativeHandle); + if (device != null) { + return device.getMode(); + } + return ErrorCodes.ERROR_INVALID_PARAM; + } + + public byte[] receive(int nativeHandle) throws RemoteException { + NativeP2pDevice device; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return null; + } + + /* find the device in the hmap */ + device = (NativeP2pDevice) findObject(nativeHandle); + if (device != null) { + byte[] buff = device.doReceive(); + if (buff == null) + return null; + return buff; + } + /* Restart polling loop for notification */ + mManager.enableDiscovery(DISCOVERY_MODE_READER); + mOpenPending = false; + return null; + } + + public boolean send(int nativeHandle, byte[] data) throws RemoteException { + NativeP2pDevice device; + boolean isSuccess = false; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return isSuccess; + } + + /* find the device in the hmap */ + device = (NativeP2pDevice) findObject(nativeHandle); + if (device != null) { + isSuccess = device.doSend(data); + } + return isSuccess; + } + }; + + private IP2pTarget mP2pTargetService = new IP2pTarget.Stub() { + + public int connect(int nativeHandle) throws RemoteException { + NativeP2pDevice device; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the device in the hmap */ + device = (NativeP2pDevice) findObject(nativeHandle); + if (device != null) { + if (device.doConnect()) { + return ErrorCodes.SUCCESS; + } + } + return ErrorCodes.ERROR_CONNECT; + } + + public boolean disconnect(int nativeHandle) throws RemoteException { + NativeP2pDevice device; + boolean isSuccess = false; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return isSuccess; + } + + /* find the device in the hmap */ + device = (NativeP2pDevice) findObject(nativeHandle); + if (device != null) { + if (isSuccess = device.doDisconnect()) { + mOpenPending = false; + /* remove the device from the hmap */ + RemoveObject(nativeHandle); + /* Restart polling loop for notification */ + mManager.enableDiscovery(DISCOVERY_MODE_READER); + } + } + return isSuccess; + + } + + public byte[] getGeneralBytes(int nativeHandle) throws RemoteException { + NativeP2pDevice device; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return null; + } + + /* find the device in the hmap */ + device = (NativeP2pDevice) findObject(nativeHandle); + if (device != null) { + byte[] buff = device.getGeneralBytes(); + if (buff == null) + return null; + return buff; + } + return null; + } + + public int getMode(int nativeHandle) throws RemoteException { + NativeP2pDevice device; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + /* find the device in the hmap */ + device = (NativeP2pDevice) findObject(nativeHandle); + if (device != null) { + return device.getMode(); + } + return ErrorCodes.ERROR_INVALID_PARAM; + } + + public byte[] transceive(int nativeHandle, byte[] data) throws RemoteException { + NativeP2pDevice device; + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return null; + } + + /* find the device in the hmap */ + device = (NativeP2pDevice) findObject(nativeHandle); + if (device != null) { + byte[] buff = device.doTransceive(data); + if (buff == null) + return null; + return buff; + } + return null; + } + }; + + private class NfcHandler extends Handler { + + @Override + public void handleMessage(Message msg) { + try { + + } catch (Exception e) { + // Log, don't crash! + Log.e(TAG, "Exception in NfcHandler.handleMessage:", e); + } + } + + }; + + public NfcService(Context context) { + super(); + mContext = context; + mManager = new NativeNfcManager(mContext); + + mContext.registerReceiver(mNfcServiceReceiver, new IntentFilter( + NativeNfcManager.INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION)); + + mContext.registerReceiver(mNfcServiceReceiver, new IntentFilter( + NfcManager.LLCP_LINK_STATE_CHANGED_ACTION)); + + mContext.registerReceiver(mNfcServiceReceiver, new IntentFilter( + NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)); + + Thread thread = new Thread(null, this, "NfcService"); + thread.start(); + + mManager.initializeNativeStructure(); + + int nfcState = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_ON, 0); + + if (nfcState == NFC_STATE_ENABLED) { + if (this._enable()) { + } + } + + } + + public void run() { + Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); + Looper.prepare(); + mNfcHandler = new NfcHandler(); + Looper.loop(); + } + + public void cancel() throws RemoteException { + mContext.enforceCallingPermission(android.Manifest.permission.NFC_RAW, + "NFC_RAW permission required to cancel NFC opening"); + if (mOpenPending) { + mOpenPending = false; + mManager.doCancel(); + /* Restart polling loop for notification */ + mManager.enableDiscovery(DISCOVERY_MODE_READER); + } + } + + public int createLlcpConnectionlessSocket(int sap) throws RemoteException { + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + mContext.enforceCallingPermission(android.Manifest.permission.NFC_LLCP, + "NFC_LLCP permission required for LLCP operations with NFC service"); + + /* Check SAP is not already used */ + + /* Check nb socket created */ + if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { + /* Store the socket handle */ + int sockeHandle = mGeneratedSocketHandle; + + if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) { + NativeLlcpConnectionlessSocket socket; + + socket = mManager.doCreateLlcpConnectionlessSocket(sap); + if (socket != null) { + /* Update the number of socket created */ + mNbSocketCreated++; + + /* Add the socket into the socket map */ + mSocketMap.put(sockeHandle, socket); + + return sockeHandle; + } else { + /* + * socket creation error - update the socket handle + * generation + */ + mGeneratedSocketHandle -= 1; + + /* Get Error Status */ + int errorStatus = mManager.doGetLastError(); + + switch (errorStatus) { + case ErrorCodes.ERROR_BUFFER_TO_SMALL: + return ErrorCodes.ERROR_BUFFER_TO_SMALL; + case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: + return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; + default: + return ErrorCodes.ERROR_SOCKET_CREATION; + } + } + } else { + /* Check SAP is not already used */ + if (!CheckSocketSap(sap)) { + return ErrorCodes.ERROR_SAP_USED; + } + + NativeLlcpConnectionlessSocket socket = new NativeLlcpConnectionlessSocket(sap); + + /* Add the socket into the socket map */ + mSocketMap.put(sockeHandle, socket); + + /* Update the number of socket created */ + mNbSocketCreated++; + + /* Create new registered socket */ + RegisteredSocket registeredSocket = new RegisteredSocket( + LLCP_CONNECTIONLESS_SOCKET_TYPE, sockeHandle, sap); + + /* Put this socket into a list of registered socket */ + mRegisteredSocketList.add(registeredSocket); + } + + /* update socket handle generation */ + mGeneratedSocketHandle++; + + return sockeHandle; + + } else { + /* No socket available */ + return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; + } + + } + + public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength) + throws RemoteException { + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + mContext.enforceCallingPermission(android.Manifest.permission.NFC_LLCP, + "NFC_LLCP permission required for LLCP operations with NFC service"); + + if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { + int sockeHandle = mGeneratedSocketHandle; + + if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) { + NativeLlcpServiceSocket socket; + + socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength); + if (socket != null) { + /* Update the number of socket created */ + mNbSocketCreated++; + /* Add the socket into the socket map */ + mSocketMap.put(sockeHandle, socket); + } else { + /* socket creation error - update the socket handle counter */ + mGeneratedSocketHandle -= 1; + + /* Get Error Status */ + int errorStatus = mManager.doGetLastError(); + + switch (errorStatus) { + case ErrorCodes.ERROR_BUFFER_TO_SMALL: + return ErrorCodes.ERROR_BUFFER_TO_SMALL; + case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: + return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; + default: + return ErrorCodes.ERROR_SOCKET_CREATION; + } + } + } else { + + /* Check SAP is not already used */ + if (!CheckSocketSap(sap)) { + return ErrorCodes.ERROR_SAP_USED; + } + + /* Service Name */ + if (!CheckSocketServiceName(sn)) { + return ErrorCodes.ERROR_SERVICE_NAME_USED; + } + + /* Check socket options */ + if (!CheckSocketOptions(miu, rw, linearBufferLength)) { + return ErrorCodes.ERROR_SOCKET_OPTIONS; + } + + NativeLlcpServiceSocket socket = new NativeLlcpServiceSocket(sn); + + /* Add the socket into the socket map */ + mSocketMap.put(sockeHandle, socket); + + /* Update the number of socket created */ + mNbSocketCreated++; + + /* Create new registered socket */ + RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SERVICE_SOCKET_TYPE, + sockeHandle, sap, sn, miu, rw, linearBufferLength); + + /* Put this socket into a list of registered socket */ + mRegisteredSocketList.add(registeredSocket); + } + + /* update socket handle generation */ + mGeneratedSocketHandle += 1; + + Log.d(TAG, "Llcp Service Socket Handle =" + sockeHandle); + return sockeHandle; + } else { + /* No socket available */ + return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; + } + } + + public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength) + throws RemoteException { + + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + mContext.enforceCallingPermission(android.Manifest.permission.NFC_LLCP, + "NFC_LLCP permission required for LLCP operations with NFC service"); + + if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) { + + int sockeHandle = mGeneratedSocketHandle; + + if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) { + NativeLlcpSocket socket; + + socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength); + + if (socket != null) { + /* Update the number of socket created */ + mNbSocketCreated++; + /* Add the socket into the socket map */ + mSocketMap.put(sockeHandle, socket); + } else { + /* + * socket creation error - update the socket handle + * generation + */ + mGeneratedSocketHandle -= 1; + + /* Get Error Status */ + int errorStatus = mManager.doGetLastError(); + + switch (errorStatus) { + case ErrorCodes.ERROR_BUFFER_TO_SMALL: + return ErrorCodes.ERROR_BUFFER_TO_SMALL; + case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES: + return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; + default: + return ErrorCodes.ERROR_SOCKET_CREATION; + } + } + } else { + + /* Check SAP is not already used */ + if (!CheckSocketSap(sap)) { + return ErrorCodes.ERROR_SAP_USED; + } + + /* Check Socket options */ + if (!CheckSocketOptions(miu, rw, linearBufferLength)) { + return ErrorCodes.ERROR_SOCKET_OPTIONS; + } + + NativeLlcpSocket socket = new NativeLlcpSocket(sap, miu, rw); + + /* Add the socket into the socket map */ + mSocketMap.put(sockeHandle, socket); + + /* Update the number of socket created */ + mNbSocketCreated++; + /* Create new registered socket */ + RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SOCKET_TYPE, + sockeHandle, sap, miu, rw, linearBufferLength); + + /* Put this socket into a list of registered socket */ + mRegisteredSocketList.add(registeredSocket); + } + + /* update socket handle generation */ + mGeneratedSocketHandle++; + + return sockeHandle; + } else { + /* No socket available */ + return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES; + } + } + + public int deselectSecureElement() throws RemoteException { + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + if (mSelectedSeId == 0) { + return ErrorCodes.ERROR_NO_SE_CONNECTED; + } + + mContext.enforceCallingPermission(android.Manifest.permission.NFC_ADMIN, + "NFC_ADMIN permission required to deselect NFC Secure Element"); + + mManager.doDeselectSecureElement(mSelectedSeId); + mNfcSecureElementState = 0; + mSelectedSeId = 0; + + /* Store that a secure element is deselected */ + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.NFC_SECURE_ELEMENT_ON, 0); + + /* Reset Secure Element ID */ + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.NFC_SECURE_ELEMENT_ID, 0); + + + return ErrorCodes.SUCCESS; + } + + public boolean disable() throws RemoteException { + boolean isSuccess = false; + mContext.enforceCallingPermission(android.Manifest.permission.NFC_ADMIN, + "NFC_ADMIN permission required to disable NFC service"); + if (isEnabled()) { + isSuccess = mManager.deinitialize(); + if (isSuccess) { + mIsNfcEnabled = false; + } + } + + updateNfcOnSetting(); + + return isSuccess; + } + + public boolean enable() throws RemoteException { + boolean isSuccess = false; + mContext.enforceCallingPermission(android.Manifest.permission.NFC_ADMIN, + "NFC_ADMIN permission required to enable NFC service"); + if (!isEnabled()) { + reset(); + isSuccess = _enable(); + } + return isSuccess; + } + + private boolean _enable() { + boolean isSuccess = mManager.initialize(); + if (isSuccess) { + /* Check persistent properties */ + checkProperties(); + + /* Check Secure Element setting */ + mNfcSecureElementState = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_SECURE_ELEMENT_ON, 0); + + if (mNfcSecureElementState == 1) { + + int secureElementId = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_SECURE_ELEMENT_ID, 0); + int[] Se_list = mManager.doGetSecureElementList(); + if (Se_list != null) { + for (int i = 0; i < Se_list.length; i++) { + if (Se_list[i] == secureElementId) { + mManager.doSelectSecureElement(Se_list[i]); + mSelectedSeId = Se_list[i]; + break; + } + } + } + } + + /* Start polling loop */ + mManager.enableDiscovery(DISCOVERY_MODE_READER); + + mIsNfcEnabled = true; + } else { + mIsNfcEnabled = false; + } + + updateNfcOnSetting(); + + return isSuccess; + } + + private void updateNfcOnSetting() { + int state; + + if (mIsNfcEnabled) { + state = NFC_STATE_ENABLED; + } else { + state = NFC_STATE_DISABLED; + } + + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_ON, state); + } + + private void checkProperties() { + int value; + + /* LLCP LTO */ + value = Settings.System.getInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_LTO, + LLCP_LTO_DEFAULT_VALUE); + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_LTO, value); + mManager.doSetProperties(PROPERTY_LLCP_LTO, value); + + /* LLCP MIU */ + value = Settings.System.getInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_MIU, + LLCP_MIU_DEFAULT_VALUE); + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_MIU, value); + mManager.doSetProperties(PROPERTY_LLCP_MIU, value); + + /* LLCP WKS */ + value = Settings.System.getInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_WKS, + LLCP_WKS_DEFAULT_VALUE); + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_WKS, value); + mManager.doSetProperties(PROPERTY_LLCP_WKS, value); + + /* LLCP OPT */ + value = Settings.System.getInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_OPT, + LLCP_OPT_DEFAULT_VALUE); + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_OPT, value); + mManager.doSetProperties(PROPERTY_LLCP_OPT, value); + + /* NFC READER A */ + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_A, 1); + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_A, + value); + mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, value); + + /* NFC READER B */ + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_B, 1); + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_B, + value); + mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, value); + + /* NFC READER F */ + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_F, 1); + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_F, + value); + mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, value); + + /* NFC READER 15693 */ + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_15693, 1); + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_15693, + value); + mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, value); + + /* NFC NFCIP */ + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_NFCIP, 1); + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_NFCIP, + value); + mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, value); + } + + public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException { + return mLlcpConnectionlessSocketService; + } + + public ILlcpSocket getLlcpInterface() throws RemoteException { + return mLlcpSocket; + } + + public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException { + return mLlcpServerSocketService; + } + + public INfcTag getNfcTagInterface() throws RemoteException { + return mNfcTagService; + } + + public int getOpenTimeout() throws RemoteException { + return mTimeout; + } + + public IP2pInitiator getP2pInitiatorInterface() throws RemoteException { + return mP2pInitiatorService; + } + + public IP2pTarget getP2pTargetInterface() throws RemoteException { + return mP2pTargetService; + } + + public String getProperties(String param) throws RemoteException { + int value; + + if (param == null) { + return "Wrong parameter"; + } + + if (param.equals(PROPERTY_LLCP_LTO_VALUE)) { + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_LLCP_LTO, 0); + } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) { + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_LLCP_MIU, 0); + } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) { + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_LLCP_WKS, 0); + } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) { + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_LLCP_OPT, 0); + } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) { + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_A, 0); + } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) { + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_B, 0); + } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) { + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_F, 0); + } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) { + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_NFCIP, 0); + } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) { + value = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_15693, 0); + } else { + return "Unknown property"; + } + + if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE) + || param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE) + || param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE) + || param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE) + || param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) { + if (value == 0) { + return "false"; + } else if (value == 1) { + return "true"; + } else { + return "Unknown Value"; + } + }else{ + return "" + value; + } + + } + + public int[] getSecureElementList() throws RemoteException { + int[] list = null; + if (mIsNfcEnabled == true) { + list = mManager.doGetSecureElementList(); + } + return list; + } + + public int getSelectedSecureElement() throws RemoteException { + return mSelectedSeId; + } + + public boolean isEnabled() throws RemoteException { + return mIsNfcEnabled; + } + + public int openP2pConnection() throws RemoteException { + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + mContext.enforceCallingPermission(android.Manifest.permission.NFC_RAW, + "NFC_RAW permission required to open NFC P2P connection"); + if (!mOpenPending) { + NativeP2pDevice device; + mOpenPending = true; + device = mManager.doOpenP2pConnection(mTimeout); + if (device != null) { + /* add device to the Hmap */ + mObjectMap.put(device.getHandle(), device); + return device.getHandle(); + } else { + mOpenPending = false; + /* Restart polling loop for notification */ + mManager.enableDiscovery(DISCOVERY_MODE_READER); + return ErrorCodes.ERROR_IO; + } + } else { + return ErrorCodes.ERROR_BUSY; + } + + } + + public int openTagConnection() throws RemoteException { + NativeNfcTag tag; + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + mContext.enforceCallingPermission(android.Manifest.permission.NFC_RAW, + "NFC_RAW permission required to open NFC Tag connection"); + if (!mOpenPending) { + mOpenPending = true; + tag = mManager.doOpenTagConnection(mTimeout); + if (tag != null) { + mObjectMap.put(tag.getHandle(), tag); + return tag.getHandle(); + } else { + mOpenPending = false; + /* Restart polling loop for notification */ + mManager.enableDiscovery(DISCOVERY_MODE_READER); + return ErrorCodes.ERROR_IO; + } + } else { + return ErrorCodes.ERROR_BUSY; + } + } + + public int selectSecureElement(int seId) throws RemoteException { + // Check if NFC is enabled + if (!mIsNfcEnabled) { + return ErrorCodes.ERROR_NOT_INITIALIZED; + } + + if (mSelectedSeId == seId) { + return ErrorCodes.ERROR_SE_ALREADY_SELECTED; + } + + if (mSelectedSeId != 0) { + return ErrorCodes.ERROR_SE_CONNECTED; + } + + mContext.enforceCallingPermission(android.Manifest.permission.NFC_ADMIN, + "NFC_ADMIN permission required to select NFC Secure Element"); + + mSelectedSeId = seId; + mManager.doSelectSecureElement(mSelectedSeId); + + /* Store that a secure element is selected */ + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.NFC_SECURE_ELEMENT_ON, 1); + + /* Store the ID of the Secure Element Selected */ + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.NFC_SECURE_ELEMENT_ID, mSelectedSeId); + + mNfcSecureElementState = 1; + + return ErrorCodes.SUCCESS; + + } + + public void setOpenTimeout(int timeout) throws RemoteException { + mContext.enforceCallingPermission(android.Manifest.permission.NFC_RAW, + "NFC_RAW permission required to set NFC connection timeout"); + mTimeout = timeout; + } + + public int setProperties(String param, String value) throws RemoteException { + mContext.enforceCallingPermission(android.Manifest.permission.NFC_ADMIN, + "NFC_ADMIN permission required to set NFC Properties"); + + if (isEnabled()) { + return ErrorCodes.ERROR_NFC_ON; + } + + int val; + + /* Check params validity */ + if (param == null || value == null) { + return ErrorCodes.ERROR_INVALID_PARAM; + } + + if (param.equals(PROPERTY_LLCP_LTO_VALUE)) { + val = Integer.parseInt(value); + + /* Check params */ + if (val > LLCP_LTO_MAX_VALUE) + return ErrorCodes.ERROR_INVALID_PARAM; + + /* Store value */ + Settings.System + .putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_LTO, val); + + /* Update JNI */ + mManager.doSetProperties(PROPERTY_LLCP_LTO, val); + + } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) { + val = Integer.parseInt(value); + + /* Check params */ + if ((val < LLCP_MIU_DEFAULT_VALUE) || (val > LLCP_MIU_MAX_VALUE)) + return ErrorCodes.ERROR_INVALID_PARAM; + + /* Store value */ + Settings.System + .putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_MIU, val); + + /* Update JNI */ + mManager.doSetProperties(PROPERTY_LLCP_MIU, val); + + } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) { + val = Integer.parseInt(value); + + /* Check params */ + if (val > LLCP_WKS_MAX_VALUE) + return ErrorCodes.ERROR_INVALID_PARAM; + + /* Store value */ + Settings.System + .putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_WKS, val); + + /* Update JNI */ + mManager.doSetProperties(PROPERTY_LLCP_WKS, val); + + } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) { + val = Integer.parseInt(value); + + /* Check params */ + if (val > LLCP_OPT_MAX_VALUE) + return ErrorCodes.ERROR_INVALID_PARAM; + + /* Store value */ + Settings.System + .putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_OPT, val); + + /* Update JNI */ + mManager.doSetProperties(PROPERTY_LLCP_OPT, val); + + } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) { + + /* Check params */ + if (value.equals("true")) { + val = 1; + } else if (value.equals("false")) { + val = 0; + } else { + return ErrorCodes.ERROR_INVALID_PARAM; + } + /* Store value */ + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_A, + val); + + /* Update JNI */ + mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, val); + + } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) { + + /* Check params */ + if (value.equals("true")) { + val = 1; + } else if (value.equals("false")) { + val = 0; + } else { + return ErrorCodes.ERROR_INVALID_PARAM; + } + + /* Store value */ + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_B, + val); + + /* Update JNI */ + mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, val); + + } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) { + + /* Check params */ + if (value.equals("true")) { + val = 1; + } else if (value.equals("false")) { + val = 0; + } else { + return ErrorCodes.ERROR_INVALID_PARAM; + } + + /* Store value */ + Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_F, + val); + + /* Update JNI */ + mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, val); + + } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) { + + /* Check params */ + if (value.equals("true")) { + val = 1; + } else if (value.equals("false")) { + val = 0; + } else { + return ErrorCodes.ERROR_INVALID_PARAM; + } + + /* Store value */ + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_15693, val); + + /* Update JNI */ + mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, val); + + } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) { + + /* Check params */ + if (value.equals("true")) { + val = 1; + } else if (value.equals("false")) { + val = 0; + } else { + return ErrorCodes.ERROR_INVALID_PARAM; + } + + /* Store value */ + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.NFC_DISCOVERY_NFCIP, val); + + /* Update JNI */ + mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, val); + } else { + return ErrorCodes.ERROR_INVALID_PARAM; + } + + return ErrorCodes.SUCCESS; + } + + // Reset all internals + private void reset() { + + // Clear tables + mObjectMap.clear(); + mSocketMap.clear(); + mRegisteredSocketList.clear(); + + // Reset variables + mLlcpLinkState = NfcManager.LLCP_LINK_STATE_DEACTIVATED; + mNbSocketCreated = 0; + mIsNfcEnabled = false; + mSelectedSeId = 0; + mTimeout = 0; + mNfcState = NFC_STATE_DISABLED; + mOpenPending = false; + } + + private Object findObject(int key) { + Object device = null; + + device = mObjectMap.get(key); + + return device; + } + + private void RemoveObject(int key) { + mObjectMap.remove(key); + } + + private Object findSocket(int key) { + Object socket = null; + + socket = mSocketMap.get(key); + + return socket; + } + + private void RemoveSocket(int key) { + mSocketMap.remove(key); + } + + private boolean CheckSocketSap(int sap) { + /* List of sockets registered */ + ListIterator it = mRegisteredSocketList.listIterator(); + + while (it.hasNext()) { + RegisteredSocket registeredSocket = it.next(); + + if (sap == registeredSocket.mSap) { + /* SAP already used */ + return false; + } + } + return true; + } + + private boolean CheckSocketOptions(int miu, int rw, int linearBufferlength) { + + if (rw > LLCP_RW_MAX_VALUE || miu < LLCP_MIU_DEFAULT_VALUE || linearBufferlength < miu) { + return false; + } + return true; + } + + private boolean CheckSocketServiceName(String sn) { + + /* List of sockets registered */ + ListIterator it = mRegisteredSocketList.listIterator(); + + while (it.hasNext()) { + RegisteredSocket registeredSocket = it.next(); + + if (sn.equals(registeredSocket.mServiceName)) { + /* Service Name already used */ + return false; + } + } + return true; + } + + private void RemoveRegisteredSocket(int nativeHandle) { + /* check if sockets are registered */ + ListIterator it = mRegisteredSocketList.listIterator(); + + while (it.hasNext()) { + RegisteredSocket registeredSocket = it.next(); + if (registeredSocket.mHandle == nativeHandle) { + /* remove the registered socket from the list */ + it.remove(); + Log.d(TAG, "socket removed"); + } + } + } + + /* + * RegisteredSocket class to store the creation request of socket until the + * LLCP link in not activated + */ + private class RegisteredSocket { + private int mType; + + private int mHandle; + + private int mSap; + + private int mMiu; + + private int mRw; + + private String mServiceName; + + private int mlinearBufferLength; + + RegisteredSocket(int type, int handle, int sap, String sn, int miu, int rw, + int linearBufferLength) { + mType = type; + mHandle = handle; + mSap = sap; + mServiceName = sn; + mRw = rw; + mMiu = miu; + mlinearBufferLength = linearBufferLength; + } + + RegisteredSocket(int type, int handle, int sap, int miu, int rw, int linearBufferLength) { + mType = type; + mHandle = handle; + mSap = sap; + mRw = rw; + mMiu = miu; + mlinearBufferLength = linearBufferLength; + } + + RegisteredSocket(int type, int handle, int sap) { + mType = type; + mHandle = handle; + mSap = sap; + } + } + + private BroadcastReceiver mNfcServiceReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + Log.d(TAG, "Internal NFC Intent received"); + + /* LLCP Link deactivation */ + if (intent.getAction().equals(NfcManager.LLCP_LINK_STATE_CHANGED_ACTION)) { + mLlcpLinkState = intent.getIntExtra(NfcManager.LLCP_LINK_STATE_CHANGED_EXTRA, + NfcManager.LLCP_LINK_STATE_DEACTIVATED); + + if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_DEACTIVATED) { + /* restart polling loop */ + mManager.enableDiscovery(DISCOVERY_MODE_READER); + } + + } + /* LLCP Link activation */ + else if (intent.getAction().equals( + NativeNfcManager.INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION)) { + + mLlcpLinkState = intent.getIntExtra( + NativeNfcManager.INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA, + NfcManager.LLCP_LINK_STATE_DEACTIVATED); + + if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) { + /* check if sockets are registered */ + ListIterator it = mRegisteredSocketList.listIterator(); + + Log.d(TAG, "Nb socket resgistered = " + mRegisteredSocketList.size()); + + while (it.hasNext()) { + RegisteredSocket registeredSocket = it.next(); + + switch (registeredSocket.mType) { + case LLCP_SERVICE_SOCKET_TYPE: + Log.d(TAG, "Registered Llcp Service Socket"); + NativeLlcpServiceSocket serviceSocket; + + serviceSocket = mManager.doCreateLlcpServiceSocket( + registeredSocket.mSap, registeredSocket.mServiceName, + registeredSocket.mMiu, registeredSocket.mRw, + registeredSocket.mlinearBufferLength); + + if (serviceSocket != null) { + /* Add the socket into the socket map */ + mSocketMap.put(registeredSocket.mHandle, serviceSocket); + } else { + /* + * socket creation error - update the socket + * handle counter + */ + mGeneratedSocketHandle -= 1; + } + break; + + case LLCP_SOCKET_TYPE: + Log.d(TAG, "Registered Llcp Socket"); + NativeLlcpSocket clientSocket; + clientSocket = mManager.doCreateLlcpSocket(registeredSocket.mSap, + registeredSocket.mMiu, registeredSocket.mRw, + registeredSocket.mlinearBufferLength); + if (clientSocket != null) { + /* Add the socket into the socket map */ + mSocketMap.put(registeredSocket.mHandle, clientSocket); + } else { + /* + * socket creation error - update the socket + * handle counter + */ + mGeneratedSocketHandle -= 1; + } + break; + + case LLCP_CONNECTIONLESS_SOCKET_TYPE: + Log.d(TAG, "Registered Llcp Connectionless Socket"); + NativeLlcpConnectionlessSocket connectionlessSocket; + connectionlessSocket = mManager + .doCreateLlcpConnectionlessSocket(registeredSocket.mSap); + if (connectionlessSocket != null) { + /* Add the socket into the socket map */ + mSocketMap.put(registeredSocket.mHandle, connectionlessSocket); + } else { + /* + * socket creation error - update the socket + * handle counter + */ + mGeneratedSocketHandle -= 1; + } + break; + + } + } + + /* Remove all registered socket from the list */ + mRegisteredSocketList.clear(); + + /* Broadcast Intent Link LLCP activated */ + Intent LlcpLinkIntent = new Intent(); + LlcpLinkIntent.setAction(NfcManager.LLCP_LINK_STATE_CHANGED_ACTION); + + LlcpLinkIntent.putExtra(NfcManager.LLCP_LINK_STATE_CHANGED_EXTRA, + NfcManager.LLCP_LINK_STATE_ACTIVATED); + + Log.d(TAG, "Broadcasting LLCP activation"); + mContext.sendOrderedBroadcast(LlcpLinkIntent, + android.Manifest.permission.NFC_LLCP); + } + } + /* Target Deactivated */ + else if (intent.getAction().equals( + NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) { + if(mOpenPending != false){ + mOpenPending = false; + } + /* Restart polling loop for notification */ + mManager.enableDiscovery(DISCOVERY_MODE_READER); + + } + } + }; +}