diff options
64 files changed, 7238 insertions, 704 deletions
@@ -159,6 +159,14 @@ LOCAL_SRC_FILES += \ core/java/com/android/internal/view/IInputMethodClient.aidl \ core/java/com/android/internal/view/IInputMethodManager.aidl \ core/java/com/android/internal/view/IInputMethodSession.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/IGeocodeProvider.aidl \ location/java/android/location/IGpsStatusListener.aidl \ location/java/android/location/IGpsStatusProvider.aidl \ diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index c01516f..e93e684 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -102,6 +102,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; @@ -171,6 +173,7 @@ class ContextImpl extends Context { private static ThrottleManager sThrottleManager; private static WifiManager sWifiManager; private static LocationManager sLocationManager; + private static NfcManager sNfcManager; private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs = new HashMap<String, SharedPreferencesImpl>(); @@ -969,6 +972,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)) { @@ -1204,6 +1209,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 0dd2e4a..693be21 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1555,6 +1555,16 @@ public abstract class Context { 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/content/res/ObbScanner.java b/core/java/android/content/res/ObbScanner.java index a3f141e..572b75e 100644 --- a/core/java/android/content/res/ObbScanner.java +++ b/core/java/android/content/res/ObbScanner.java @@ -42,7 +42,7 @@ public class ObbScanner { final File obbFile = new File(filePath); if (!obbFile.exists()) { - throw new IllegalArgumentException("OBB file does nto exist: " + filePath); + throw new IllegalArgumentException("OBB file does not exist: " + filePath); } final String canonicalFilePath = obbFile.getCanonicalPath(); diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index e56e257..6d19f41 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -68,6 +68,7 @@ public class RecoverySystem { private static File RECOVERY_DIR = new File("/cache/recovery"); private static File COMMAND_FILE = new File(RECOVERY_DIR, "command"); private static File LOG_FILE = new File(RECOVERY_DIR, "log"); + private static String LAST_LOG_FILENAME = "last_log"; // Length limits for reading files. private static int LOG_FILE_MAX_LENGTH = 64 * 1024; @@ -399,9 +400,10 @@ public class RecoverySystem { Log.e(TAG, "Error reading recovery log", e); } - // Delete everything in RECOVERY_DIR + // Delete everything in RECOVERY_DIR except LAST_LOG_FILENAME String[] names = RECOVERY_DIR.list(); for (int i = 0; names != null && i < names.length; i++) { + if (names[i].equals(LAST_LOG_FILENAME)) continue; File f = new File(RECOVERY_DIR, names[i]); if (!f.delete()) { Log.e(TAG, "Can't delete: " + f); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 1dd2420..90cd840 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1640,6 +1640,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 * 1 = yes @@ -1804,7 +1884,19 @@ public final class Settings { SHOW_WEB_SUGGESTIONS, NOTIFICATION_LIGHT_PULSE, 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/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index e05fe7b..bcb151a 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -225,10 +225,10 @@ class BluetoothEventLoop { } String name = propValues[0]; if (name.equals("Name")) { + mBluetoothService.setProperty(name, propValues[1]); Intent intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, propValues[1]); mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mBluetoothService.setProperty(name, propValues[1]); } else if (name.equals("Pairable") || name.equals("Discoverable")) { String pairable = name.equals("Pairable") ? propValues[1] : mBluetoothService.getPropertyInternal("Pairable"); @@ -239,6 +239,7 @@ class BluetoothEventLoop { if (pairable == null || discoverable == null) return; + mBluetoothService.setProperty(name, propValues[1]); int mode = BluetoothService.bluezStringToScanMode( pairable.equals("true"), discoverable.equals("true")); @@ -248,9 +249,9 @@ class BluetoothEventLoop { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); mContext.sendBroadcast(intent, BLUETOOTH_PERM); } - mBluetoothService.setProperty(name, propValues[1]); } else if (name.equals("Discovering")) { Intent intent; + mBluetoothService.setProperty(name, propValues[1]); if (propValues[1].equals("true")) { mBluetoothService.setIsDiscovering(true); intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED); @@ -261,7 +262,6 @@ class BluetoothEventLoop { intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); } mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mBluetoothService.setProperty(name, propValues[1]); } else if (name.equals("Devices")) { String value = null; int len = Integer.valueOf(propValues[1]); @@ -294,19 +294,20 @@ class BluetoothEventLoop { } BluetoothDevice device = mAdapter.getRemoteDevice(address); if (name.equals("Name")) { + mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); Intent intent = new Intent(BluetoothDevice.ACTION_NAME_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothDevice.EXTRA_NAME, propValues[1]); mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); } else if (name.equals("Class")) { + mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); Intent intent = new Intent(BluetoothDevice.ACTION_CLASS_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); intent.putExtra(BluetoothDevice.EXTRA_CLASS, new BluetoothClass(Integer.valueOf(propValues[1]))); mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); } else if (name.equals("Connected")) { + mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); Intent intent = null; if (propValues[1].equals("true")) { intent = new Intent(BluetoothDevice.ACTION_ACL_CONNECTED); @@ -320,7 +321,6 @@ class BluetoothEventLoop { } intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); mContext.sendBroadcast(intent, BLUETOOTH_PERM); - mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]); } else if (name.equals("UUIDs")) { String uuid = null; int len = Integer.valueOf(propValues[1]); 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 0000000..35746ad --- /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 0000000..5eb1f3c --- /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 0000000..e9169d8 --- /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 0000000..1f8d1a4 --- /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 0000000..ce36ab2 --- /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 0000000..79543c4 --- /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 0000000..96819ae --- /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 0000000..8dcdf18 --- /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 0000000..0270626 --- /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 0000000..1e2e2da --- /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 0000000..297a1fe --- /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 0000000..af79023 --- /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<LlcpPacket> CREATOR = new Parcelable.Creator<LlcpPacket>() { + 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 0000000..a152ecb1 --- /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 0000000..e47160c --- /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. + * <p> + * 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. + * <p> + * 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 0000000..e60f4e8 --- /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 0000000..f03b604 --- /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 <a + * href="http://www.nfc-forum.org/">NFC Forum</a>. + * + * @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<NdefMessage> CREATOR = new Parcelable.Creator<NdefMessage>() { + 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 0000000..9d95174 --- /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 0000000..a0257fe --- /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 <a href="http://www.nfc-forum.org/">NFC + * Forum</a>. + * + * @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<NdefRecord> CREATOR = new Parcelable.Creator<NdefRecord>() { + 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 0000000..1d99241 --- /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 0000000..2497c15 --- /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 0000000..98ab5bf --- /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. + * <p> + * 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. + * <p> + * Always contains the extra field + * {@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_MESSAGE_EXTRA}. + * <p class="note"> + * <strong>Note:</strong> 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. + * <p> + * Always contains the extra field + * {@link com.trustedlogic.trustednfc.android.NfcManager#AID_EXTRA} + * <p class="note"> + * <strong>Note:</strong> 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. + * <p> + * Always contains the extra field + * {@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_EXTRA}. + * <p class="note"> + * <strong>Note:</strong> 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 + * <p class="note"> + * <strong>Note:</strong> 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 + * <p class="note"> + * <strong>Note:</strong> 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. + * <p class="note"> + * <strong>Note:</strong> 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 + * <p class="note"> + * <strong>Note:</strong> 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. + * <p class="note"> + * <strong>Note:</strong> 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. + * <p class="note"> + * <strong>Note:</strong> 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 + * <p class="note"> + * <strong>Note:</strong> 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 + * <p class="note"> + * <strong>Note:</strong> 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) + * <p class="note"> + * <strong>Note:</strong> 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). + * <p> + * 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. + * <p class="note"> + * <strong>Note:</strong> 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) + * <p> + * 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. + * <p class="note"> + * <strong>Note:</strong> 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. + * <p class="note"> + * <strong>Note:</strong> 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 0000000..798c7e4 --- /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. + * <p> + * + * <pre class="prettyprint"> + * if (tag.isNdef()) { + * NdefTag ndefTag = (NdefTag) tag; + * NdefMessage msg = ndefTag.read(); + * } + * </pre> + * + * @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 0000000..65800f2 --- /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 0000000..0f28ae0 --- /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 0000000..b5e00db --- /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 0000000..ca3b7e0 --- /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 0000000..ccfbeb4 --- /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 0000000..a01f135 --- /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 0000000..077c5e0 --- /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 0000000..d1e64a6 --- /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 0000000..2f5a0f0 --- /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 0000000..b92783d --- /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 0000000..75d25ba --- /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 0000000..0c0b605 --- /dev/null +++ b/core/java/com/trustedlogic/trustednfc/android/package.html @@ -0,0 +1,473 @@ +<html> +<body> + +<p>Provides classes that manage the NFC functionality.</p> + +<p>The NFC functionality is related to Near Field Communication.</p> + +<p>The NFC APIs let applications:</p> +<ul> + <li>Scan for remote NFC targets (NFC Tag or NFC Peer)</li> + <li>Transfer raw data to and from remote NFC targets (NFC Tags or NFC Peer)</li> + <li>Read/Write NDEF data from/to remote NFC targets (NFC Tags)</li> + <li>Establish LLCP connection with a remote NFC target (NFC Peer with LLCP support)</li> + <li>Exchange data with a remote NFC target through LLCP services (NFC Peer with LLCP support)</li> + <li>Be notified of transactions on the local Secure Element by an external NFC reader</li> +</ul> + + +<h1>Setting Up NFC</h1> + +<p> +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. +</p> + +<pre> + NfcManager mNfcManager = (NfcManager) getSystemService(Context.NFC_SERVICE); + if (mNfcManager == null) { + // Device does not support NFC + } +</pre> + +<p> +An application can ensure that NFC is enabled. +If not, an application with the needed permission can request that NFC be +enabled. +</p> + +<pre> + if (!mNfcManager.isEnabled) { + // NFC is currently disabled. + // Enable NFC. + mNfcManager.enable(); + } +</pre> + +<p> +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}). +</p> + +<p> +Before using the NFC feature, an application can configure the NFC device by +calling {@link com.trustedlogic.trustednfc.android.NfcManager#setProperties}. This function allows: +</p> +<ul> + <li>Enabling/disabling the NFC device capabilities (RF types, baudrates, + NFCIP-1 mode and role...)</li> + <li>Settings the NFCIP-1 general bytes and the LLCP link parameters</li> +</ul> +<p> +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. +</p> +<table> + <TR><TH> Property Name </TH><TH> Property Values </TH></TR> + <TR><TD> discovery.felica </TD><TD> <b>true</b>|false </TD></TR> + <TR><TD> discovery.iso14443A </TD><TD> <b>true</b>|false </TD></TR> + <TR><TD> discovery.iso14443B </TD><TD> <b>true</b>|false </TD></TR> + <TR><TD> discovery.iso15693 </TD><TD> <b>true</b>|false </TD></TR> + <TR><TD> discovery.nfcip </TD><TD> <b>true</b>|false </TD></TR> + <TR><TD> nfcip.baudrate </TD><TD> 106|212|424 </TD></TR> + <TR><TD> nfcip.generalbytes </TD><TD> </TD></TR> + <TR><TD> nfcip.mode </TD><TD> active|passive|<b>all</b> </TD></TR> + <TR><TD> nfcip.role </TD><TD> initiator|target|<b>both</b> </TD></TR> + <TR><TD> llcp.lto </TD><TD> <b>150</b> (0 to 255) </TD></TR> + <TR><TD> llcp.opt </TD><TD> <b>0</b> (0 to 3) </TD></TR> + <TR><TD> llcp.miu </TD><TD> <b>128</b> (128 to 2176) </TD></TR> + <TR><TD> llcp.wks </TD><TD> <b>1</b> (0 to 15) </TD></TR> +</table> +<p>(default values in bold)</p> + + +<h1>NFC Permissions</h1> + +<p> +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. +</p> +<p> +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. +</p> +<p> +To receive NDEF message or Secure Element intents, an application must declare +the NFC_NOTIFY permission. +</p> +<p> +To receive the LLCP link intent and perform an LLCP communication with a remote NFC target, an application must +declare the NFC_LLCP permission. +</p> + + +<h1>NFC Usage</h1> + +<p> +The following code samples illustrate the APIs usage regarding the NFC service +use cases. +</p> + +<h2>Reader/Writer Mode NDEF message notification</h2> + +<p> +This code sample illustrates the NDEF message notification through an Intent declared in the manifest and a receiver implemented in the application. +</p> +<p>Main involved classes/methods:</p> + +<p>Manifest Example:</p> +<pre> + <receiver android:name=".NfcReaderDemoReceiver"> + <intent-filter> + <action android:name= "com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED"/> + </intent-filter> + </receiver> +</pre> + +<p>Receiver Example:</p> +<ul> + <li>{@link com.trustedlogic.trustednfc.android.NdefMessage}</li> + <li>{@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_TAG_DISCOVERED_ACTION}</li> + <li>{@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_MESSAGE_EXTRA}</li> +</ul> +<pre> +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 */ + } +</pre> + +<h2>Reader/Writer Mode raw exchange</h2> + +<p> +This code sample illustrates raw exchanges with a NFC target in Reader/Writer +mode. +</p> +<p>Main involved classes/methods:</p> +<ul> + <li>{@link com.trustedlogic.trustednfc.android.NfcManager#openTagConnection}</li> + <li>{@link com.trustedlogic.trustednfc.android.NfcTag}</li> +</ul> + +<pre> +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(); + } + } + } + } +} +</pre> + +<h2>Peer-to-Peer Mode raw exchange</h2> + +<p> +This code sample illustrates raw exchanges with a NFC target in Peer-to-Peer +mode. +</p> +<p>Main involved classes/methods:</p> +<ul> + <li>{@link com.trustedlogic.trustednfc.android.NfcManager#openP2pConnection}</li> + <li>{@link com.trustedlogic.trustednfc.android.P2pDevice}</li> + <li>{@link com.trustedlogic.trustednfc.android.P2pInitiator}</li> + <li>{@link com.trustedlogic.trustednfc.android.P2pTarget}</li> +</ul> + +<pre> +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) { + + } + } +} +</pre> + +<h2>Peer-to-Peer Mode LLCP exchange</h2> + +<p> +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. +</p> +<p>Manifest Example:</p> +<pre> + <receiver android:name=".LlcpModeReceiverSample"> + <intent-filter> + <action android:name= "com.trustedlogic.trustednfc.android.action.LLCP_LINK_STATE_CHANGED"/> + </intent-filter> + </receiver> +</pre> + +<p>Receiver Example:</p> +<ul> + <li>{@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_ACTION}</li> + <li>{@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_EXTRA}</li> +</ul> +<pre> +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 */ + } + } +</pre> + + +<p> +This code samples illustrate LLCP exchanges with a NFC Peer. +</p> +<p>Main involved classes/methods:</p> +<ul> + <li>{@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpSocket}</li> + <li>{@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpConnectionlessSocket}</li> + <li>{@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpServiceSocket}</li> + <li>{@link com.trustedlogic.trustednfc.android.LlcpSocket}</li> + <li>{@link com.trustedlogic.trustednfc.android.LlcpConnectionlessSocket}</li> + <li>{@link com.trustedlogic.trustednfc.android.LlcpPacket}</li> + <li>{@link com.trustedlogic.trustednfc.android.LlcpServiceSocket}</li> +</ul> + +<pre> +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 + } + } +} +</pre> + +<pre> +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) + } + } +} +</pre> + +<h2>Card Emulation Mode transaction notification</h2> + +<p> +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. +</p> +<p>Manifest Example:</p> +<pre> + <receiver android:name=".NfcReaderDemoReceiver"> + <intent-filter> + <action android:name= "com.trustedlogic.trustednfc.android.action.TRANSACTION_DETECTED"/> + </intent-filter> + </receiver> +</pre> + +<p>Receiver Example:</p> +<ul> + <li>{@link com.trustedlogic.trustednfc.android.NfcManager#TRANSACTION_DETECTED_ACTION}</li> + <li>{@link com.trustedlogic.trustednfc.android.NfcManager#AID_EXTRA}</li> +</ul> +<pre> +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 */ + } + } +</pre> + + + +<h1>Multiple Applications rules</h1> + +<p> +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. +</p> + +<p> +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. +</p> + +<p> +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. +</p> + +<p> +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. +</p> + + +<h1>NFC Tag types</h1> + +<p> +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}. +</p> + +<TABLE BORDER="1"> + <TR><TH> Tag Type </TH><TH> Returned string </TH></TR> + <TR><TD> Jewel/Topaz </TD><TD> Jewel </TD></TR> + <TR><TD> Mifare UltraLight </TD><TD> MifareUL </TD></TR> + <TR><TD> Mifare Standard 1K </TD><TD> Mifare1K </TD></TR> + <TR><TD> Mifare Standard 4K </TD><TD> Mifare4K </TD></TR> + <TR><TD> Mifare DESFIRE </TD><TD> MifareDESFIRE </TD></TR> + <TR><TD> Felica </TD><TD> Felica </TD></TR> + <TR><TD> ISO14443-4 A or B </TD><TD> Iso14443 </TD></TR> + <TR><TD> ISO15693 </TD><TD> Iso15693 </TD></TR> +</TABLE> + +</body> +</html> diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 8c280b4..f4d1b6e 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -193,6 +193,14 @@ LOCAL_SHARED_LIBRARIES := \ libwpa_client \ libjpeg +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 beb49c8..e5d5d8a 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 68a5a14..b9eb5d6 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -86,6 +86,10 @@ <protected-broadcast android:name="android.hardware.action.USB_DISCONNECTED" /> <protected-broadcast android:name="android.hardware.action.USB_STATE" /> + <protected-broadcast android:name="com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED" /> + <protected-broadcast android:name="com.trustedlogic.trustednfc.android.action.TRANSACTION_DETECTED" /> + <protected-broadcast android:name="com.trustedlogic.trustednfc.android.action.LLCP_LINK_STATE_CHANGED" /> + <!-- ====================================== --> <!-- Permissions for things that cost money --> <!-- ====================================== --> @@ -336,6 +340,30 @@ android:description="@string/permdesc_bluetooth" android:label="@string/permlab_bluetooth" /> + <!-- Allows applications to access remote NFC devices + @hide --> + <permission android:name="com.trustedlogic.trustednfc.permission.NFC_RAW" + android:permissionGroup="android.permission-group.NETWORK" + android:protectionLevel="dangerous" + android:description="@string/permdesc_nfcRaw" + android:label="@string/permlab_nfcRaw" /> + + <!-- Allows applications to be notified of remote NFC devices + @hide --> + <permission android:name="com.trustedlogic.trustednfc.permission.NFC_NOTIFY" + android:permissionGroup="android.permission-group.NETWORK" + android:protectionLevel="dangerous" + android:description="@string/permdesc_nfcNotify" + android:label="@string/permlab_nfcNotify" /> + + <!-- Allows applications to be notified of remote NFC LLCP devices + @hide --> + <permission android:name="com.trustedlogic.trustednfc.permission.NFC_LLCP" + android:permissionGroup="android.permission-group.NETWORK" + android:protectionLevel="dangerous" + android:description="@string/permdesc_nfcLlcp" + android:label="@string/permlab_nfcLlcp" /> + <!-- Allows applications to call into AccountAuthenticators. Only the system can get this permission. --> <permission android:name="android.permission.ACCOUNT_MANAGER" @@ -839,6 +867,14 @@ android:description="@string/permdesc_bluetoothAdmin" android:label="@string/permlab_bluetoothAdmin" /> + <!-- Allows applications to change NFC connectivity settings + @hide --> + <permission android:name="com.trustedlogic.trustednfc.permission.NFC_ADMIN" + android:permissionGroup="android.permission-group.SYSTEM_TOOLS" + android:protectionLevel="dangerous" + android:description="@string/permdesc_nfcAdmin" + android:label="@string/permlab_nfcAdmin" /> + <!-- Allows an application to clear the caches of all installed applications on the device. --> <permission android:name="android.permission.CLEAR_APP_CACHE" diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index ebccfb6..d9177e7 100644..100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -381,8 +381,10 @@ <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> <string name="permgrouplab_storage">Storage</string> + <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] --> + <string name="permgroupdesc_storage" product="nosdcard">Access the shared storage.</string> <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permgroupdesc_storage">Access the SD card.</string> + <string name="permgroupdesc_storage" product="default">Access the SD card.</string> <!-- Permissions --> @@ -1151,6 +1153,30 @@ connections with paired devices.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_nfcAdmin">NFC administration</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_nfcAdmin">Allows an application to configure + the local NFC phone.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_nfcRaw">NFC full access to remote device</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_nfcRaw">Allows an application to access + remote NFC devices.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_nfcNotify">NFC notification from remote device</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_nfcNotify">Allows an application to be notified + of operations related to remote NFC devices.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_nfcLlcp">NFC notification from remote LLCP device</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_nfcLlcp">Allows an application to be notified + of LLCP operations related to remote NFC devices.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_disableKeyguard">disable keylock</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_disableKeyguard">Allows an application to disable @@ -1200,10 +1226,14 @@ <string name="permdesc_writeDictionary">Allows an application to write new words into the user dictionary.</string> + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] --> + <string name="permlab_sdcardWrite" product="nosdcard">modify/delete shared storage contents</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permlab_sdcardWrite">modify/delete SD card contents</string> + <string name="permlab_sdcardWrite" product="default">modify/delete SD card contents</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=30] --> + <string name="permdesc_sdcardWrite" product="nosdcard">Allows an application to write to the shared storage.</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_sdcardWrite">Allows an application to write to the SD card.</string> + <string name="permdesc_sdcardWrite" product="default">Allows an application to write to the SD card.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_cache_filesystem">access the cache filesystem</string> @@ -1213,31 +1243,28 @@ <!-- Policy administration --> <!-- Title of policy access to limiting the user's password choices --> - <string name="policylab_limitPassword">Limit password</string> + <string name="policylab_limitPassword">Set password rules</string> <!-- Description of policy access to limiting the user's password choices --> - <string name="policydesc_limitPassword">Restrict the types of passwords you - are allowed to use.</string> + <string name="policydesc_limitPassword">Control the length and the characters allowed in + screen-unlock passwords</string> <!-- Title of policy access to watch user login attempts --> - <string name="policylab_watchLogin">Watch login attempts</string> + <string name="policylab_watchLogin">Monitor screen-unlock attempts</string> <!-- Description of policy access to watch user login attempts --> - <string name="policydesc_watchLogin">Monitor failed attempts to login to - the device, to perform some action.</string> + <string name="policydesc_watchLogin">Monitor the number of incorrect passwords entered when unlocking + the screen, and lock the phone or erase all the phone\'s data if too many incorrect passwords are entered + </string> <!-- Title of policy access to reset user's password --> - <string name="policylab_resetPassword">Reset password</string> + <string name="policylab_resetPassword">Change the screen-unlock password</string> <!-- Description of policy access to reset user's password --> - <string name="policydesc_resetPassword">Force your password - to a new value, requiring the administrator give it to you - before you can log in.</string> + <string name="policydesc_resetPassword">Change the screen-unlock password</string> <!-- Title of policy access to force lock the device --> - <string name="policylab_forceLock">Force lock</string> + <string name="policylab_forceLock">Lock the screen</string> <!-- Description of policy access to limiting the user's password choices --> - <string name="policydesc_forceLock">Control when device locks, - requiring you re-enter its password.</string> + <string name="policydesc_forceLock">Control how and when the screen locks</string> <!-- Title of policy access to wipe the user's data --> <string name="policylab_wipeData">Erase all data</string> <!-- Description of policy access to wipe the user's data --> - <string name="policydesc_wipeData">Perform a factory reset, deleting - all of your data without any confirmation.</string> + <string name="policydesc_wipeData">Erase the phone\'s data without warning, by performing a factory data reset</string> <!-- The order of these is important, don't reorder without changing Contacts.java --> <skip /> <!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. --> @@ -2058,12 +2085,16 @@ <!-- See USB_STORAGE. USB_STORAGE_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to mount. This is the title. --> <string name="usb_storage_title">USB connected</string> + <!-- See USB_STORAGE. This is the message. [CHAR LIMIT=NONE] --> + <string name="usb_storage_message" product="nosdcard">You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\u2018s shared storage.</string> <!-- See USB_STORAGE. This is the message. --> - <string name="usb_storage_message">You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\u2018s SD card.</string> + <string name="usb_storage_message" product="default">You have connected your phone to your computer via USB. Select the button below if you want to copy files between your computer and your Android\u2018s SD card.</string> <!-- See USB_STORAGE. This is the button text to mount the phone on the computer. --> <string name="usb_storage_button_mount">Turn on USB storage</string> + <!-- See USB_STORAGE_DIALOG. If there was an error mounting, this is the text. [CHAR LIMIT=NONE] --> + <string name="usb_storage_error_message" product="nosdcard">There is a problem using your shared storage for USB storage.</string> <!-- See USB_STORAGE_DIALOG. If there was an error mounting, this is the text. --> - <string name="usb_storage_error_message">There is a problem using your SD card for USB storage.</string> + <string name="usb_storage_error_message" product="default">There is a problem using your SD card for USB storage.</string> <!-- USB_STORAGE: When the user connects the phone to a computer via USB, we show a notification asking if he wants to share files across. This is the title --> <string name="usb_storage_notification_title">USB connected</string> <!-- See USB_STORAGE. This is the message. --> @@ -2078,8 +2109,10 @@ <!-- This is the label for the activity, and should never be visible to the user. --> <!-- See USB_STORAGE_STOP. USB_STORAGE_STOP_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to stop usb storage. This is the title. --> <string name="usb_storage_stop_title">USB storage in use</string> + <!-- See USB_STORAGE_STOP. This is the message. [CHAR LIMIT=NONE] --> + <string name="usb_storage_stop_message" product="nosdcard">Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s shared storage from your computer.</string> <!-- See USB_STORAGE_STOP. This is the message. --> - <string name="usb_storage_stop_message">Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s SD card from your computer.</string> + <string name="usb_storage_stop_message" product="default">Before turning off USB storage, make sure you have unmounted (\u201cejected\u201d) your Android\u2018s SD card from your computer.</string> <!-- See USB_STORAGE_STOP. This is the button text to stop usb storage. --> <string name="usb_storage_stop_button_mount">Turn off USB storage</string> <!-- See USB_STORAGE_STOP_DIALOG. If there was an error stopping, this is the text. --> @@ -2096,10 +2129,14 @@ <!-- External media format dialog strings --> <!-- This is the label for the activity, and should never be visible to the user. --> + <!-- See EXTMEDIA_FORMAT. EXTMEDIA_FORMAT_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to format the SD card. This is the title. [CHAR LIMIT=20] --> + <string name="extmedia_format_title" product="nosdcard">Format shared storage</string> <!-- See EXTMEDIA_FORMAT. EXTMEDIA_FORMAT_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to format the SD card. This is the title. --> - <string name="extmedia_format_title">Format SD card</string> + <string name="extmedia_format_title" product="default">Format SD card</string> + <!-- See EXTMEDIA_FORMAT. This is the message. [CHAR LIMIT=NONE] --> + <string name="extmedia_format_message" product="nosdcard">Format shared storage, erasing all files stored there? Action cannot be reversed!</string> <!-- See EXTMEDIA_FORMAT. This is the message. --> - <string name="extmedia_format_message">Are you sure you want to format the SD card? All data on your card will be lost.</string> + <string name="extmedia_format_message" product="default">Are you sure you want to format the SD card? All data on your card will be lost.</string> <!-- See EXTMEDIA_FORMAT. This is the button text to format the sd card. --> <string name="extmedia_format_button_format">Format</string> @@ -2124,29 +2161,51 @@ <string name="candidates_style"><u>candidates</u></string> <!-- External media notification strings --> + <!-- Shown when external media is being checked [CHAR LIMIT=30] --> + <string name="ext_media_checking_notification_title" product="nosdcard">Preparing shared storage</string> <!-- Shown when external media is being checked --> - <string name="ext_media_checking_notification_title">Preparing SD card</string> + <string name="ext_media_checking_notification_title" product="default">Preparing SD card</string> <string name="ext_media_checking_notification_message">Checking for errors.</string> + <!-- Shown when external media is blank (or unsupported filesystem) [CHAR LIMIT=30] --> + <string name="ext_media_nofs_notification_title" product="nosdcard">Blank shared storage</string> <!-- Shown when external media is blank (or unsupported filesystem) --> - <string name="ext_media_nofs_notification_title">Blank SD card</string> - <string name="ext_media_nofs_notification_message">SD card blank or has unsupported filesystem.</string> + <string name="ext_media_nofs_notification_title" product="default">Blank SD card</string> + <!-- Shown when shared storage cannot be read. [CHAR LIMIT=NONE] --> + <string name="ext_media_nofs_notification_message" product="nosdcard">Shared storage blank or has unsupported filesystem.</string> + <string name="ext_media_nofs_notification_message" product="default">SD card blank or has unsupported filesystem.</string> + <!-- Shown when external media is unmountable (corrupt)) [CHAR LIMIT=30] --> + <string name="ext_media_unmountable_notification_title" product="nosdcard">Damaged shared storage</string> <!-- Shown when external media is unmountable (corrupt)) --> - <string name="ext_media_unmountable_notification_title">Damaged SD card</string> - <string name="ext_media_unmountable_notification_message">SD card damaged. You may have to reformat it.</string> + <string name="ext_media_unmountable_notification_title" product="default">Damaged SD card</string> + <!-- Shown when shared storage cannot be read. [CHAR LIMIT=NONE] --> + <string name="ext_media_unmountable_notification_message" product="nosdcard">Shared storage damaged. You may have to reformat it.</string> + <string name="ext_media_unmountable_notification_message" product="default">SD card damaged. You may have to reformat it.</string> + <!-- Shown when external media is unsafely removed [CHAR LIMIT=30] --> + <string name="ext_media_badremoval_notification_title" product="nosdcard">Shared storage unexpectedly removed</string> <!-- Shown when external media is unsafely removed --> - <string name="ext_media_badremoval_notification_title">SD card unexpectedly removed</string> - <string name="ext_media_badremoval_notification_message">Unmount SD card before removing to avoid data loss.</string> + <string name="ext_media_badremoval_notification_title" product="default">SD card unexpectedly removed</string> + <!-- Shown when external media is unsafely removed. [CHAR LIMIT=NONE] --> + <string name="ext_media_badremoval_notification_message" product="nosdcard">Unmount shared storage before removing to avoid data loss.</string> + <string name="ext_media_badremoval_notification_message" product="default">Unmount SD card before removing to avoid data loss.</string> + <!-- Shown when external media has been safely removed [CHAR LIMIT=30] --> + <string name="ext_media_safe_unmount_notification_title" product="nosdcard">Shared storage safe to remove</string> <!-- Shown when external media has been safely removed --> - <string name="ext_media_safe_unmount_notification_title">SD card safe to remove</string> - <string name="ext_media_safe_unmount_notification_message">You can safely remove SD card.</string> + <string name="ext_media_safe_unmount_notification_title" product="default">SD card safe to remove</string> + <!-- Shown when external media has been safely removed. [CHAR LIMIT=NONE] --> + <string name="ext_media_safe_unmount_notification_message" product="nosdcard">You can safely remove shared storage.</string> + <string name="ext_media_safe_unmount_notification_message" product="default">You can safely remove SD card.</string> + <!-- Shown when external media is missing [CHAR LIMIT=30] --> + <string name="ext_media_nomedia_notification_title" product="nosdcard">Removed shared storage</string> <!-- Shown when external media is missing --> - <string name="ext_media_nomedia_notification_title">Removed SD card</string> - <string name="ext_media_nomedia_notification_message">SD card removed. Insert a new one.</string> + <string name="ext_media_nomedia_notification_title" product="default">Removed SD card</string> + <!-- Shown when external media is missing. [CHAR LIMIT=NONE] --> + <string name="ext_media_nomedia_notification_message" product="nosdcard">Shared storage removed. Insert new media.</string> + <string name="ext_media_nomedia_notification_message" product="default">SD card removed. Insert a new one.</string> <!-- Shown in LauncherActivity when the requested target Intent didn't return any matching Activities, leaving the list empty. --> <string name="activity_list_empty">No matching activities found</string> diff --git a/location/java/android/location/provider/GeocodeProvider.java b/location/java/android/location/provider/GeocodeProvider.java deleted file mode 100644 index 493c631..0000000 --- a/location/java/android/location/provider/GeocodeProvider.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 android.location.provider; - -import android.os.IBinder; - -import android.location.Address; -import android.location.GeocoderParams; -import android.location.IGeocodeProvider; - -import java.util.List; - -/** - * An abstract superclass for geocode providers that are implemented - * outside of the core android platform. - * Geocode providers can be implemented as services and return the result of - * {@link GeocodeProvider#getBinder()} in its getBinder() method. - * - * @hide - */ -public abstract class GeocodeProvider { - - private IGeocodeProvider.Stub mProvider = new IGeocodeProvider.Stub() { - public String getFromLocation(double latitude, double longitude, int maxResults, - GeocoderParams params, List<Address> addrs) { - return GeocodeProvider.this.onGetFromLocation(latitude, longitude, maxResults, - params, addrs); - } - - public String getFromLocationName(String locationName, - double lowerLeftLatitude, double lowerLeftLongitude, - double upperRightLatitude, double upperRightLongitude, int maxResults, - GeocoderParams params, List<Address> addrs) { - return GeocodeProvider.this.onGetFromLocationName(locationName, lowerLeftLatitude, - lowerLeftLongitude, upperRightLatitude, upperRightLongitude, - maxResults, params, addrs); - } - }; - - /** - * This method is overridden to implement the - * {@link android.location.Geocoder#getFromLocation(double, double, int)} method. - * Classes implementing this method should not hold a reference to the params parameter. - */ - public abstract String onGetFromLocation(double latitude, double longitude, int maxResults, - GeocoderParams params, List<Address> addrs); - - /** - * This method is overridden to implement the - * {@link android.location.Geocoder#getFromLocationName(String, int, double, double, double, double)} method. - * Classes implementing this method should not hold a reference to the params parameter. - */ - public abstract String onGetFromLocationName(String locationName, - double lowerLeftLatitude, double lowerLeftLongitude, - double upperRightLatitude, double upperRightLongitude, int maxResults, - GeocoderParams params, List<Address> addrs); - - /** - * Returns the Binder interface for the geocode provider. - * This is intended to be used for the onBind() method of - * a service that implements a geocoder service. - * - * @return the IBinder instance for the provider - */ - public IBinder getBinder() { - return mProvider; - } -} - diff --git a/location/java/android/location/provider/LocationProvider.java b/location/java/android/location/provider/LocationProvider.java deleted file mode 100644 index 14dea14..0000000 --- a/location/java/android/location/provider/LocationProvider.java +++ /dev/null @@ -1,359 +0,0 @@ -/* - * 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 android.location.provider; - -import android.content.Context; -import android.net.NetworkInfo; -import android.location.Criteria; -import android.location.ILocationManager; -import android.location.ILocationProvider; -import android.location.Location; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.WorkSource; -import android.util.Log; - -/** - * An abstract superclass for location providers that are implemented - * outside of the core android platform. - * Location providers can be implemented as services and return the result of - * {@link LocationProvider#getBinder()} in its getBinder() method. - * - * @hide - */ -public abstract class LocationProvider { - - private static final String TAG = "LocationProvider"; - - private ILocationManager mLocationManager; - - private ILocationProvider.Stub mProvider = new ILocationProvider.Stub() { - - public boolean requiresNetwork() { - return LocationProvider.this.onRequiresNetwork(); - } - - public boolean requiresSatellite() { - return LocationProvider.this.onRequiresSatellite(); - } - - public boolean requiresCell() { - return LocationProvider.this.onRequiresCell(); - } - - public boolean hasMonetaryCost() { - return LocationProvider.this.onHasMonetaryCost(); - } - - public boolean supportsAltitude() { - return LocationProvider.this.onSupportsAltitude(); - } - - public boolean supportsSpeed() { - return LocationProvider.this.onSupportsSpeed(); - } - - public boolean supportsBearing() { - return LocationProvider.this.onSupportsBearing(); - } - - public int getPowerRequirement() { - return LocationProvider.this.onGetPowerRequirement(); - } - - public boolean meetsCriteria(Criteria criteria) { - return LocationProvider.this.onMeetsCriteria(criteria); - } - - public int getAccuracy() { - return LocationProvider.this.onGetAccuracy(); - } - - public void enable() { - LocationProvider.this.onEnable(); - } - - public void disable() { - LocationProvider.this.onDisable(); - } - - public int getStatus(Bundle extras) { - return LocationProvider.this.onGetStatus(extras); - } - - public long getStatusUpdateTime() { - return LocationProvider.this.onGetStatusUpdateTime(); - } - - public String getInternalState() { - return LocationProvider.this.onGetInternalState(); - } - - public void enableLocationTracking(boolean enable) { - LocationProvider.this.onEnableLocationTracking(enable); - } - - public void setMinTime(long minTime, WorkSource ws) { - LocationProvider.this.onSetMinTime(minTime, ws); - } - - public void updateNetworkState(int state, NetworkInfo info) { - LocationProvider.this.onUpdateNetworkState(state, info); - } - - public void updateLocation(Location location) { - LocationProvider.this.onUpdateLocation(location); - } - - public boolean sendExtraCommand(String command, Bundle extras) { - return LocationProvider.this.onSendExtraCommand(command, extras); - } - - public void addListener(int uid) { - LocationProvider.this.onAddListener(uid, new WorkSource(uid)); - } - - public void removeListener(int uid) { - LocationProvider.this.onRemoveListener(uid, new WorkSource(uid)); - } - }; - - public LocationProvider() { - IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE); - mLocationManager = ILocationManager.Stub.asInterface(b); - } - - /** - * {@hide} - */ - /* package */ ILocationProvider getInterface() { - return mProvider; - } - - /** - * Returns the Binder interface for the location provider. - * This is intended to be used for the onBind() method of - * a service that implements a location provider service. - * - * @return the IBinder instance for the provider - */ - public IBinder getBinder() { - return mProvider; - } - - /** - * Used by the location provider to report new locations. - * - * @param location new Location to report - * - * Requires the android.permission.INSTALL_LOCATION_PROVIDER permission. - */ - public void reportLocation(Location location) { - try { - mLocationManager.reportLocation(location, false); - } catch (RemoteException e) { - Log.e(TAG, "RemoteException in reportLocation: ", e); - } - } - - /** - * Returns true if the provider requires access to a - * data network (e.g., the Internet), false otherwise. - */ - public abstract boolean onRequiresNetwork(); - - /** - * Returns true if the provider requires access to a - * satellite-based positioning system (e.g., GPS), false - * otherwise. - */ - public abstract boolean onRequiresSatellite(); - - /** - * Returns true if the provider requires access to an appropriate - * cellular network (e.g., to make use of cell tower IDs), false - * otherwise. - */ - public abstract boolean onRequiresCell(); - - /** - * Returns true if the use of this provider may result in a - * monetary charge to the user, false if use is free. It is up to - * each provider to give accurate information. - */ - public abstract boolean onHasMonetaryCost(); - - /** - * Returns true if the provider is able to provide altitude - * information, false otherwise. A provider that reports altitude - * under most circumstances but may occassionally not report it - * should return true. - */ - public abstract boolean onSupportsAltitude(); - - /** - * Returns true if the provider is able to provide speed - * information, false otherwise. A provider that reports speed - * under most circumstances but may occassionally not report it - * should return true. - */ - public abstract boolean onSupportsSpeed(); - - /** - * Returns true if the provider is able to provide bearing - * information, false otherwise. A provider that reports bearing - * under most circumstances but may occassionally not report it - * should return true. - */ - public abstract boolean onSupportsBearing(); - - /** - * Returns the power requirement for this provider. - * - * @return the power requirement for this provider, as one of the - * constants Criteria.POWER_REQUIREMENT_*. - */ - public abstract int onGetPowerRequirement(); - - /** - * Returns true if this provider meets the given criteria, - * false otherwise. - */ - public abstract boolean onMeetsCriteria(Criteria criteria); - - /** - * Returns a constant describing horizontal accuracy of this provider. - * If the provider returns finer grain or exact location, - * {@link Criteria#ACCURACY_FINE} is returned, otherwise if the - * location is only approximate then {@link Criteria#ACCURACY_COARSE} - * is returned. - */ - public abstract int onGetAccuracy(); - - /** - * Enables the location provider - */ - public abstract void onEnable(); - - /** - * Disables the location provider - */ - public abstract void onDisable(); - - /** - * Returns a information on the status of this provider. - * {@link android.location.LocationProvider#OUT_OF_SERVICE} is returned if the provider is - * out of service, and this is not expected to change in the near - * future; {@link android.location.LocationProvider#TEMPORARILY_UNAVAILABLE} is returned if - * the provider is temporarily unavailable but is expected to be - * available shortly; and {@link android.location.LocationProvider#AVAILABLE} is returned - * if the provider is currently available. - * - * <p> If extras is non-null, additional status information may be - * added to it in the form of provider-specific key/value pairs. - */ - public abstract int onGetStatus(Bundle extras); - - /** - * Returns the time at which the status was last updated. It is the - * responsibility of the provider to appropriately set this value using - * {@link android.os.SystemClock#elapsedRealtime SystemClock.elapsedRealtime()}. - * there is a status update that it wishes to broadcast to all its - * listeners. The provider should be careful not to broadcast - * the same status again. - * - * @return time of last status update in millis since last reboot - */ - public abstract long onGetStatusUpdateTime(); - - /** - * Returns debugging information about the location provider. - * - * @return string describing the internal state of the location provider, or null. - */ - public abstract String onGetInternalState(); - - /** - * Notifies the location provider that clients are listening for locations. - * Called with enable set to true when the first client is added and - * called with enable set to false when the last client is removed. - * This allows the provider to prepare for receiving locations, - * and to shut down when no clients are remaining. - * - * @param enable true if location tracking should be enabled. - */ - public abstract void onEnableLocationTracking(boolean enable); - - /** - * Notifies the location provider of the smallest minimum time between updates amongst - * all clients that are listening for locations. This allows the provider to reduce - * the frequency of updates to match the requested frequency. - * - * @param minTime the smallest minTime value over all listeners for this provider. - * @param ws the source this work is coming from. - */ - public abstract void onSetMinTime(long minTime, WorkSource ws); - - /** - * Updates the network state for the given provider. This function must - * be overwritten if {@link android.location.LocationProvider#requiresNetwork} returns true. - * The state is {@link android.location.LocationProvider#TEMPORARILY_UNAVAILABLE} (disconnected) - * OR {@link android.location.LocationProvider#AVAILABLE} (connected or connecting). - * - * @param state data state - */ - public abstract void onUpdateNetworkState(int state, NetworkInfo info); - - /** - * Informs the provider when a new location has been computed by a different - * location provider. This is intended to be used as aiding data for the - * receiving provider. - * - * @param location new location from other location provider - */ - public abstract void onUpdateLocation(Location location); - - /** - * Implements addditional location provider specific additional commands. - * - * @param command name of the command to send to the provider. - * @param extras optional arguments for the command (or null). - * The provider may optionally fill the extras Bundle with results from the command. - * - * @return true if the command succeeds. - */ - public abstract boolean onSendExtraCommand(String command, Bundle extras); - - /** - * Notifies the location provider when a new client is listening for locations. - * - * @param uid user ID of the new client. - * @param ws a WorkSource representation of the client. - */ - public abstract void onAddListener(int uid, WorkSource ws); - - /** - * Notifies the location provider when a client is no longer listening for locations. - * - * @param uid user ID of the client no longer listening. - * @param ws a WorkSource representation of the client. - */ - public abstract void onRemoveListener(int uid, WorkSource ws); -} - diff --git a/media/libstagefright/codecs/amrnb/common/include/frame_type_3gpp.h b/media/libstagefright/codecs/amrnb/common/include/frame_type_3gpp.h index 0620367..3ebd929 100644 --- a/media/libstagefright/codecs/amrnb/common/include/frame_type_3gpp.h +++ b/media/libstagefright/codecs/amrnb/common/include/frame_type_3gpp.h @@ -87,22 +87,22 @@ extern "C" enum Frame_Type_3GPP { - AMR_475 = 0, - AMR_515, - AMR_59, - AMR_67, - AMR_74, - AMR_795, - AMR_102, - AMR_122, - AMR_SID, - GSM_EFR_SID, - TDMA_EFR_SID, - PDC_EFR_SID, - FOR_FUTURE_USE1, - FOR_FUTURE_USE2, - FOR_FUTURE_USE3, - AMR_NO_DATA + AMR_475 = 0, /* 4.75 kbps */ + AMR_515, /* 5.15 kbps */ + AMR_59, /* 5.9 kbps */ + AMR_67, /* 6.7 kbps */ + AMR_74, /* 7.4 kbps */ + AMR_795, /* 7.95 kbps */ + AMR_102, /* 10.2 kbps */ + AMR_122, /* 12.2 kbps */ + AMR_SID, /* GSM AMR DTX */ + GSM_EFR_SID, /* GSM EFR DTX */ + TDMA_EFR_SID, /* TDMA EFR DTX */ + PDC_EFR_SID, /* PDC EFR DTX */ + FOR_FUTURE_USE1, /* Unused 1 */ + FOR_FUTURE_USE2, /* Unused 2 */ + FOR_FUTURE_USE3, /* Unused 3 */ + AMR_NO_DATA /* No data */ }; /*---------------------------------------------------------------------------- diff --git a/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h b/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h index 673a94a..a9fdb1c 100644 --- a/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h +++ b/media/libstagefright/codecs/amrnb/dec/src/gsmamr_dec.h @@ -87,6 +87,8 @@ terms listed above has been obtained from the copyright holder. #include "gsm_amr_typedefs.h" #include "pvamrnbdecoder_api.h" +#include "frame_type_3gpp.h" + /*--------------------------------------------------------------------------*/ #ifdef __cplusplus extern "C" @@ -117,25 +119,6 @@ extern "C" /*---------------------------------------------------------------------------- ; ENUMERATED TYPEDEF'S ----------------------------------------------------------------------------*/ - enum Frame_Type_3GPP - { - AMR_475 = 0, /* 4.75 kbps */ - AMR_515, /* 5.15 kbps */ - AMR_59, /* 5.9 kbps */ - AMR_67, /* 6.7 kbps */ - AMR_74, /* 7.4 kbps */ - AMR_795, /* 7.95 kbps */ - AMR_102, /* 10.2 kbps */ - AMR_122, /* 12.2 kbps */ - AMR_SID, /* GSM AMR DTX */ - GSM_EFR_SID, /* GSM EFR DTX */ - TDMA_EFR_SID, /* TDMA EFR DTX */ - PDC_EFR_SID, /* PDC EFR DTX */ - FOR_FUTURE_USE1, /* Unused 1 */ - FOR_FUTURE_USE2, /* Unused 2 */ - FOR_FUTURE_USE3, /* Unused 3 */ - AMR_NO_DATA - }; /* No data */ /*---------------------------------------------------------------------------- ; STRUCTURES TYPEDEF'S diff --git a/media/libstagefright/codecs/amrnb/enc/src/gsmamr_enc.h b/media/libstagefright/codecs/amrnb/enc/src/gsmamr_enc.h index 390a44d..67c7aa3 100644 --- a/media/libstagefright/codecs/amrnb/enc/src/gsmamr_enc.h +++ b/media/libstagefright/codecs/amrnb/enc/src/gsmamr_enc.h @@ -86,6 +86,7 @@ terms listed above has been obtained from the copyright holder. ----------------------------------------------------------------------------*/ #include "gsm_amr_typedefs.h" +#include "frame_type_3gpp.h" /*--------------------------------------------------------------------------*/ #ifdef __cplusplus @@ -137,26 +138,6 @@ extern "C" N_MODES /* Not Used */ }; - enum Frame_Type_3GPP - { - AMR_475 = 0, /* 4.75 kbps */ - AMR_515, /* 5.15 kbps */ - AMR_59, /* 5.9 kbps */ - AMR_67, /* 6.7 kbps */ - AMR_74, /* 7.4 kbps */ - AMR_795, /* 7.95 kbps */ - AMR_102, /* 10.2 kbps */ - AMR_122, /* 12.2 kbps */ - AMR_SID, /* GSM AMR DTX */ - GSM_EFR_SID, /* GSM EFR DTX */ - TDMA_EFR_SID, /* TDMA EFR DTX */ - PDC_EFR_SID, /* PDC EFR DTX */ - FOR_FUTURE_USE1, /* Unused 1 */ - FOR_FUTURE_USE2, /* Unused 2 */ - FOR_FUTURE_USE3, /* Unused 3 */ - AMR_NO_DATA /* No data */ - }; - /*---------------------------------------------------------------------------- ; STRUCTURES TYPEDEF'S ----------------------------------------------------------------------------*/ diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png Binary files differindex 157491e..a0e59cf 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_no_sim.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png Binary files differindex aea18ed..1626895 100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png Binary files differindex 1a25a2c..3c2e2b9 100755..100644 --- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png +++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1_fully.png diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png Binary files differindex 2134d49..bb41db0 100644 --- a/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png +++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_no_sim.png diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java index f3625a8..265d613 100644 --- a/services/java/com/android/server/MountService.java +++ b/services/java/com/android/server/MountService.java @@ -1451,11 +1451,6 @@ class MountService extends IMountService.Stub mHandler.sendEmptyMessage(H_UNMOUNT_PM_DONE); } - private boolean isCallerOwnerOfPackageOrSystem(String packageName) { - final int callerUid = Binder.getCallingUid(); - return isUidOwnerOfPackageOrSystem(packageName, callerUid); - } - private boolean isUidOwnerOfPackageOrSystem(String packageName, int callerUid) { if (callerUid == android.os.Process.SYSTEM_UID) { return true; @@ -1507,6 +1502,12 @@ class MountService extends IMountService.Stub waitForReady(); warnOnNotMounted(); + if (filename == null) { + throw new IllegalArgumentException("filename cannot be null"); + } else if (token == null) { + throw new IllegalArgumentException("token cannot be null"); + } + final ObbState obbState; synchronized (mObbMounts) { @@ -1533,6 +1534,12 @@ class MountService extends IMountService.Stub } public void unmountObb(String filename, boolean force, IObbActionListener token) { + if (filename == null) { + throw new IllegalArgumentException("filename cannot be null"); + } else if (token == null) { + throw new IllegalArgumentException("token cannot be null"); + } + final ObbState obbState; synchronized (mObbMounts) { @@ -1540,6 +1547,12 @@ class MountService extends IMountService.Stub throw new IllegalArgumentException("OBB is not mounted"); } obbState = mObbPathToStateMap.get(filename); + + if (Binder.getCallingUid() != obbState.callerUid) { + throw new SecurityException("caller UID does not match original mount caller UID"); + } else if (!token.asBinder().equals(obbState.token.asBinder())) { + throw new SecurityException("caller does not match original mount caller"); + } } UnmountObbAction action = new UnmountObbAction(obbState, force); @@ -1758,9 +1771,9 @@ class MountService extends IMountService.Stub } public void handleExecute() throws RemoteException, IOException { - ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename); + final ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename); if (obbInfo == null) { - throw new IOException("Couldn't read OBB file"); + throw new IOException("Couldn't read OBB file: " + mObbState.filename); } if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mObbState.callerUid)) { @@ -1833,13 +1846,9 @@ class MountService extends IMountService.Stub } public void handleExecute() throws RemoteException, IOException { - ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename); + final ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename); if (obbInfo == null) { - throw new IOException("Couldn't read OBB file"); - } - - if (!isCallerOwnerOfPackageOrSystem(obbInfo.packageName)) { - throw new IllegalArgumentException("Caller package does not match OBB file"); + throw new IOException("Couldn't read OBB file: " + mObbState.filename); } int rc = StorageResultCode.OperationSucceeded; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index a80ab1d..7f42429 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; @@ -41,6 +42,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 android.accounts.AccountManagerService; @@ -409,6 +411,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 0000000..431b798 --- /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<Integer, Object> mObjectMap = new HashMap<Integer, Object>(); + + private HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>(); + + private LinkedList<RegisteredSocket> mRegisteredSocketList = new LinkedList<RegisteredSocket>(); + + 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<RegisteredSocket> 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<RegisteredSocket> 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<RegisteredSocket> 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<RegisteredSocket> 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); + + } + } + }; +} diff --git a/voip/java/android/net/rtp/AudioCodec.java b/voip/java/android/net/rtp/AudioCodec.java index 4851a46..f171806 100644 --- a/voip/java/android/net/rtp/AudioCodec.java +++ b/voip/java/android/net/rtp/AudioCodec.java @@ -81,7 +81,7 @@ public class AudioCodec { public static final AudioCodec AMR = new AudioCodec(97, "AMR/8000", null); // TODO: add rest of the codecs when the native part is done. - private static final AudioCodec[] sCodecs = {PCMU, PCMA}; + private static final AudioCodec[] sCodecs = {GSM_EFR, GSM, PCMU, PCMA}; private AudioCodec(int type, String rtpmap, String fmtp) { this.type = type; diff --git a/voip/jni/rtp/AmrCodec.cpp b/voip/jni/rtp/AmrCodec.cpp new file mode 100644 index 0000000..9a2227d --- /dev/null +++ b/voip/jni/rtp/AmrCodec.cpp @@ -0,0 +1,97 @@ +/* + * Copyrightm (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. + */ + +#include "AudioCodec.h" + +#include "gsmamr_dec.h" +#include "gsmamr_enc.h" + +namespace { + +class GsmEfrCodec : public AudioCodec +{ +public: + GsmEfrCodec() { + if (AMREncodeInit(&mEncoder, &mSidSync, false)) { + mEncoder = NULL; + } + if (GSMInitDecode(&mDecoder, (Word8 *)"RTP")) { + mDecoder = NULL; + } + } + + ~GsmEfrCodec() { + if (mEncoder) { + AMREncodeExit(&mEncoder, &mSidSync); + } + if (mDecoder) { + GSMDecodeFrameExit(&mDecoder); + } + } + + int set(int sampleRate, const char *fmtp) { + return (sampleRate == 8000 && mEncoder && mDecoder) ? 160 : -1; + } + + int encode(void *payload, int16_t *samples); + int decode(int16_t *samples, void *payload, int length); + +private: + void *mEncoder; + void *mSidSync; + void *mDecoder; +}; + +int GsmEfrCodec::encode(void *payload, int16_t *samples) +{ + unsigned char *bytes = (unsigned char *)payload; + Frame_Type_3GPP type; + + int length = AMREncode(mEncoder, mSidSync, MR122, + samples, bytes, &type, AMR_TX_WMF); + + if (type == AMR_122 && length == 32) { + bytes[0] = 0xC0 | (bytes[1] >> 4); + for (int i = 1; i < 31; ++i) { + bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4); + } + return 31; + } + return -1; +} + +int GsmEfrCodec::decode(int16_t *samples, void *payload, int length) +{ + unsigned char *bytes = (unsigned char *)payload; + if (length == 31 && (bytes[0] >> 4) == 0x0C) { + for (int i = 0; i < 30; ++i) { + bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4); + } + bytes[30] <<= 4; + + if (AMRDecode(mDecoder, AMR_122, bytes, samples, MIME_IETF) == 31) { + return 160; + } + } + return -1; +} + +} // namespace + +AudioCodec *newGsmEfrCodec() +{ + return new GsmEfrCodec; +} diff --git a/voip/jni/rtp/Android.mk b/voip/jni/rtp/Android.mk index a364355..5909c0d 100644 --- a/voip/jni/rtp/Android.mk +++ b/voip/jni/rtp/Android.mk @@ -26,16 +26,29 @@ LOCAL_SRC_FILES := \ util.cpp \ rtp_jni.cpp +LOCAL_SRC_FILES += \ + AmrCodec.cpp \ + G711Codec.cpp \ + GsmCodec.cpp + LOCAL_SHARED_LIBRARIES := \ libnativehelper \ libcutils \ libutils \ - libmedia + libmedia \ + libstagefright -LOCAL_STATIC_LIBRARIES := +LOCAL_STATIC_LIBRARIES := libgsm LOCAL_C_INCLUDES += \ - $(JNI_H_INCLUDE) + $(JNI_H_INCLUDE) \ + external/libgsm/inc \ + frameworks/base/media/libstagefright/codecs/amrnb/common/include \ + frameworks/base/media/libstagefright/codecs/amrnb/common/ \ + frameworks/base/media/libstagefright/codecs/amrnb/enc/include \ + frameworks/base/media/libstagefright/codecs/amrnb/enc/src \ + frameworks/base/media/libstagefright/codecs/amrnb/dec/include \ + frameworks/base/media/libstagefright/codecs/amrnb/dec/src LOCAL_CFLAGS += -fvisibility=hidden diff --git a/voip/jni/rtp/AudioCodec.cpp b/voip/jni/rtp/AudioCodec.cpp index 4d8d36c..afc193c 100644 --- a/voip/jni/rtp/AudioCodec.cpp +++ b/voip/jni/rtp/AudioCodec.cpp @@ -18,124 +18,10 @@ #include "AudioCodec.h" -namespace { - -int8_t gExponents[128] = { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, -}; - -//------------------------------------------------------------------------------ - -class UlawCodec : public AudioCodec -{ -public: - int set(int sampleRate, const char *fmtp) { - mSampleCount = sampleRate / 50; - return mSampleCount; - } - int encode(void *payload, int16_t *samples); - int decode(int16_t *samples, void *payload, int length); -private: - int mSampleCount; -}; - -int UlawCodec::encode(void *payload, int16_t *samples) -{ - int8_t *ulaws = (int8_t *)payload; - for (int i = 0; i < mSampleCount; ++i) { - int sample = samples[i]; - int sign = (sample >> 8) & 0x80; - if (sample < 0) { - sample = -sample; - } - sample += 132; - if (sample > 32767) { - sample = 32767; - } - int exponent = gExponents[sample >> 8]; - int mantissa = (sample >> (exponent + 3)) & 0x0F; - ulaws[i] = ~(sign | (exponent << 4) | mantissa); - } - return mSampleCount; -} - -int UlawCodec::decode(int16_t *samples, void *payload, int length) -{ - int8_t *ulaws = (int8_t *)payload; - for (int i = 0; i < length; ++i) { - int ulaw = ~ulaws[i]; - int exponent = (ulaw >> 4) & 0x07; - int mantissa = ulaw & 0x0F; - int sample = (((mantissa << 3) + 132) << exponent) - 132; - samples[i] = (ulaw < 0 ? -sample : sample); - } - return length; -} - -AudioCodec *newUlawCodec() -{ - return new UlawCodec; -} - -//------------------------------------------------------------------------------ - -class AlawCodec : public AudioCodec -{ -public: - int set(int sampleRate, const char *fmtp) { - mSampleCount = sampleRate / 50; - return mSampleCount; - } - int encode(void *payload, int16_t *samples); - int decode(int16_t *samples, void *payload, int length); -private: - int mSampleCount; -}; - -int AlawCodec::encode(void *payload, int16_t *samples) -{ - int8_t *alaws = (int8_t *)payload; - for (int i = 0; i < mSampleCount; ++i) { - int sample = samples[i]; - int sign = (sample >> 8) & 0x80; - if (sample < 0) { - sample = -sample; - } - if (sample > 32767) { - sample = 32767; - } - int exponent = gExponents[sample >> 8]; - int mantissa = (sample >> (exponent == 0 ? 4 : exponent + 3)) & 0x0F; - alaws[i] = (sign | (exponent << 4) | mantissa) ^ 0xD5; - } - return mSampleCount; -} - -int AlawCodec::decode(int16_t *samples, void *payload, int length) -{ - int8_t *alaws = (int8_t *)payload; - for (int i = 0; i < length; ++i) { - int alaw = alaws[i] ^ 0x55; - int exponent = (alaw >> 4) & 0x07; - int mantissa = alaw & 0x0F; - int sample = (exponent == 0 ? (mantissa << 4) + 8 : - ((mantissa << 3) + 132) << exponent); - samples[i] = (alaw < 0 ? sample : -sample); - } - return length; -} - -AudioCodec *newAlawCodec() -{ - return new AlawCodec; -} +extern AudioCodec *newAlawCodec(); +extern AudioCodec *newUlawCodec(); +extern AudioCodec *newGsmCodec(); +extern AudioCodec *newGsmEfrCodec(); struct AudioCodecType { const char *name; @@ -143,11 +29,11 @@ struct AudioCodecType { } gAudioCodecTypes[] = { {"PCMA", newAlawCodec}, {"PCMU", newUlawCodec}, + {"GSM", newGsmCodec}, + {"GSM-EFR", newGsmEfrCodec}, {NULL, NULL}, }; -} // namespace - AudioCodec *newAudioCodec(const char *codecName) { AudioCodecType *type = gAudioCodecTypes; diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp index 72c882b..f09edb6 100644 --- a/voip/jni/rtp/AudioGroup.cpp +++ b/voip/jni/rtp/AudioGroup.cpp @@ -86,8 +86,6 @@ public: void decode(int tick); private: - bool isNatAddress(struct sockaddr_storage *addr); - enum { NORMAL = 0, SEND_ONLY = 1, @@ -101,6 +99,7 @@ private: AudioCodec *mCodec; uint32_t mCodecMagic; uint32_t mDtmfMagic; + bool mFixRemote; int mTick; int mSampleRate; @@ -181,6 +180,20 @@ bool AudioStream::set(int mode, int socket, sockaddr_storage *remote, if (codec) { mRemote = *remote; mCodec = codec; + + // Here we should never get an private address, but some buggy proxy + // servers do give us one. To solve this, we replace the address when + // the first time we successfully decode an incoming packet. + mFixRemote = false; + if (remote->ss_family == AF_INET) { + unsigned char *address = + (unsigned char *)&((sockaddr_in *)remote)->sin_addr; + if (address[0] == 10 || + (address[0] == 172 && (address[1] >> 4) == 1) || + (address[0] == 192 && address[1] == 168)) { + mFixRemote = true; + } + } } LOGD("stream[%d] is configured as %s %dkHz %dms", mSocket, @@ -318,16 +331,6 @@ void AudioStream::encode(int tick, AudioStream *chain) sizeof(mRemote)); } -bool AudioStream::isNatAddress(struct sockaddr_storage *addr) { - if (addr->ss_family != AF_INET) return false; - struct sockaddr_in *s4 = (struct sockaddr_in *)addr; - unsigned char *d = (unsigned char *) &s4->sin_addr; - if ((d[0] == 10) - || ((d[0] == 172) && (d[1] & 0x10)) - || ((d[0] == 192) && (d[1] == 168))) return true; - return false; -} - void AudioStream::decode(int tick) { char c; @@ -375,21 +378,11 @@ void AudioStream::decode(int tick) MSG_TRUNC | MSG_DONTWAIT) >> 1; } else { __attribute__((aligned(4))) uint8_t buffer[2048]; - struct sockaddr_storage src_addr; - socklen_t addrlen; + sockaddr_storage remote; + socklen_t len = sizeof(remote); + length = recvfrom(mSocket, buffer, sizeof(buffer), - MSG_TRUNC|MSG_DONTWAIT, (sockaddr*)&src_addr, &addrlen); - - // The following if clause is for fixing the target address if - // proxy server did not replace the NAT address with its media - // port in SDP. Although it is proxy server's responsibility for - // replacing the connection address with correct one, we will change - // the target address as we detect the difference for now until we - // know the best way to get rid of this issue. - if ((memcmp((void*)&src_addr, (void*)&mRemote, addrlen) != 0) && - isNatAddress(&mRemote)) { - memcpy((void*)&mRemote, (void*)&src_addr, addrlen); - } + MSG_TRUNC | MSG_DONTWAIT, (sockaddr *)&remote, &len); // Do we need to check SSRC, sequence, and timestamp? They are not // reliable but at least they can be used to identify duplicates? @@ -409,8 +402,12 @@ void AudioStream::decode(int tick) if (length >= 0) { length = mCodec->decode(samples, &buffer[offset], length); } + if (length > 0 && mFixRemote) { + mRemote = remote; + mFixRemote = false; + } } - if (length != mSampleCount) { + if (length <= 0) { LOGD("stream[%d] decoder error", mSocket); return; } diff --git a/voip/jni/rtp/G711Codec.cpp b/voip/jni/rtp/G711Codec.cpp new file mode 100644 index 0000000..091afa9 --- /dev/null +++ b/voip/jni/rtp/G711Codec.cpp @@ -0,0 +1,138 @@ +/* + * Copyrightm (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. + */ + +#include "AudioCodec.h" + +namespace { + +int8_t gExponents[128] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, +}; + +//------------------------------------------------------------------------------ + +class UlawCodec : public AudioCodec +{ +public: + int set(int sampleRate, const char *fmtp) { + mSampleCount = sampleRate / 50; + return mSampleCount; + } + int encode(void *payload, int16_t *samples); + int decode(int16_t *samples, void *payload, int length); +private: + int mSampleCount; +}; + +int UlawCodec::encode(void *payload, int16_t *samples) +{ + int8_t *ulaws = (int8_t *)payload; + for (int i = 0; i < mSampleCount; ++i) { + int sample = samples[i]; + int sign = (sample >> 8) & 0x80; + if (sample < 0) { + sample = -sample; + } + sample += 132; + if (sample > 32767) { + sample = 32767; + } + int exponent = gExponents[sample >> 8]; + int mantissa = (sample >> (exponent + 3)) & 0x0F; + ulaws[i] = ~(sign | (exponent << 4) | mantissa); + } + return mSampleCount; +} + +int UlawCodec::decode(int16_t *samples, void *payload, int length) +{ + int8_t *ulaws = (int8_t *)payload; + for (int i = 0; i < length; ++i) { + int ulaw = ~ulaws[i]; + int exponent = (ulaw >> 4) & 0x07; + int mantissa = ulaw & 0x0F; + int sample = (((mantissa << 3) + 132) << exponent) - 132; + samples[i] = (ulaw < 0 ? -sample : sample); + } + return length; +} + +//------------------------------------------------------------------------------ + +class AlawCodec : public AudioCodec +{ +public: + int set(int sampleRate, const char *fmtp) { + mSampleCount = sampleRate / 50; + return mSampleCount; + } + int encode(void *payload, int16_t *samples); + int decode(int16_t *samples, void *payload, int length); +private: + int mSampleCount; +}; + +int AlawCodec::encode(void *payload, int16_t *samples) +{ + int8_t *alaws = (int8_t *)payload; + for (int i = 0; i < mSampleCount; ++i) { + int sample = samples[i]; + int sign = (sample >> 8) & 0x80; + if (sample < 0) { + sample = -sample; + } + if (sample > 32767) { + sample = 32767; + } + int exponent = gExponents[sample >> 8]; + int mantissa = (sample >> (exponent == 0 ? 4 : exponent + 3)) & 0x0F; + alaws[i] = (sign | (exponent << 4) | mantissa) ^ 0xD5; + } + return mSampleCount; +} + +int AlawCodec::decode(int16_t *samples, void *payload, int length) +{ + int8_t *alaws = (int8_t *)payload; + for (int i = 0; i < length; ++i) { + int alaw = alaws[i] ^ 0x55; + int exponent = (alaw >> 4) & 0x07; + int mantissa = alaw & 0x0F; + int sample = (exponent == 0 ? (mantissa << 4) + 8 : + ((mantissa << 3) + 132) << exponent); + samples[i] = (alaw < 0 ? sample : -sample); + } + return length; +} + +} // namespace + +AudioCodec *newUlawCodec() +{ + return new UlawCodec; +} + +AudioCodec *newAlawCodec() +{ + return new AlawCodec; +} diff --git a/voip/jni/rtp/GsmCodec.cpp b/voip/jni/rtp/GsmCodec.cpp new file mode 100644 index 0000000..8d2286e --- /dev/null +++ b/voip/jni/rtp/GsmCodec.cpp @@ -0,0 +1,74 @@ +/* + * Copyrightm (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. + */ + +#include "AudioCodec.h" + +extern "C" { +#include "gsm.h" +} + +namespace { + +class GsmCodec : public AudioCodec +{ +public: + GsmCodec() { + mEncode = gsm_create(); + mDecode = gsm_create(); + } + + ~GsmCodec() { + if (mEncode) { + gsm_destroy(mEncode); + } + if (mDecode) { + gsm_destroy(mDecode); + } + } + + int set(int sampleRate, const char *fmtp) { + return (sampleRate == 8000 && mEncode && mDecode) ? 160 : -1; + } + + int encode(void *payload, int16_t *samples); + int decode(int16_t *samples, void *payload, int length); + +private: + gsm mEncode; + gsm mDecode; +}; + +int GsmCodec::encode(void *payload, int16_t *samples) +{ + gsm_encode(mEncode, samples, (unsigned char *)payload); + return 33; +} + +int GsmCodec::decode(int16_t *samples, void *payload, int length) +{ + if (length == 33 && + gsm_decode(mDecode, (unsigned char *)payload, samples) == 0) { + return 160; + } + return -1; +} + +} // namespace + +AudioCodec *newGsmCodec() +{ + return new GsmCodec; +} |