summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/com/android/nfc/DeviceHost.java20
-rw-r--r--src/com/android/nfc/FireflyRenderer.java1
-rw-r--r--src/com/android/nfc/NfcApplication.java24
-rw-r--r--src/com/android/nfc/NfcDispatcher.java42
-rw-r--r--src/com/android/nfc/NfcRootActivity.java4
-rwxr-xr-xsrc/com/android/nfc/NfcService.java405
-rw-r--r--src/com/android/nfc/P2pEventManager.java53
-rwxr-xr-xsrc/com/android/nfc/P2pLinkManager.java18
-rw-r--r--src/com/android/nfc/RegisteredComponentCache.java31
-rw-r--r--src/com/android/nfc/SendUi.java20
-rw-r--r--src/com/android/nfc/handover/BluetoothHeadsetHandover.java231
-rw-r--r--src/com/android/nfc/handover/HandoverManager.java55
-rwxr-xr-xsrc/com/android/nfc/ndefpush/NdefPushServer.java67
-rwxr-xr-xsrc/com/android/nfc/nxp/NativeLlcpConnectionlessSocket.java78
-rwxr-xr-xsrc/com/android/nfc/nxp/NativeLlcpServiceSocket.java53
-rwxr-xr-xsrc/com/android/nfc/nxp/NativeLlcpSocket.java99
-rwxr-xr-xsrc/com/android/nfc/nxp/NativeNfcManager.java388
-rwxr-xr-xsrc/com/android/nfc/nxp/NativeNfcSecureElement.java67
-rwxr-xr-xsrc/com/android/nfc/nxp/NativeNfcTag.java803
-rwxr-xr-xsrc/com/android/nfc/nxp/NativeP2pDevice.java77
-rw-r--r--src/com/android/nfc/snep/SnepClient.java24
-rw-r--r--src/com/android/nfc/snep/SnepServer.java22
22 files changed, 690 insertions, 1892 deletions
diff --git a/src/com/android/nfc/DeviceHost.java b/src/com/android/nfc/DeviceHost.java
index 022c804..bfd5d9c 100755
--- a/src/com/android/nfc/DeviceHost.java
+++ b/src/com/android/nfc/DeviceHost.java
@@ -49,6 +49,16 @@ public interface DeviceHost {
public void onRemoteFieldDeactivated();
+ /**
+ * Notifies that the SE has been activated in listen mode
+ */
+ public void onSeListenActivated();
+
+ /**
+ * Notifies that the SE has been deactivated
+ */
+ public void onSeListenDeactivated();
+
public void onSeApduReceived(byte[] apdu);
public void onSeEmvCardRemoval();
@@ -175,6 +185,8 @@ public interface DeviceHost {
public boolean deinitialize();
+ public String getName();
+
public void enableDiscovery();
public void disableDiscovery();
@@ -224,5 +236,13 @@ public interface DeviceHost {
boolean getExtendedLengthApdusSupported();
+ boolean enablePN544Quirks();
+
+ byte[][] getWipeApdus();
+
+ int getDefaultLlcpMiu();
+
+ int getDefaultLlcpRwSize();
+
String dump();
}
diff --git a/src/com/android/nfc/FireflyRenderer.java b/src/com/android/nfc/FireflyRenderer.java
index 4ce58b4..40c931d 100644
--- a/src/com/android/nfc/FireflyRenderer.java
+++ b/src/com/android/nfc/FireflyRenderer.java
@@ -200,6 +200,7 @@ public class FireflyRenderer {
for (int i = 0; i < 3; i++) {
// Call eglSwapBuffers 3 times - this will allocate the necessary
// buffers, and make sure the animation looks smooth from the start.
+ mGL.glClear(GL10.GL_COLOR_BUFFER_BIT);
if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
Log.e(LOG_TAG, "Could not swap buffers");
mFinished = true;
diff --git a/src/com/android/nfc/NfcApplication.java b/src/com/android/nfc/NfcApplication.java
new file mode 100644
index 0000000..867b8bb
--- /dev/null
+++ b/src/com/android/nfc/NfcApplication.java
@@ -0,0 +1,24 @@
+package com.android.nfc;
+
+import android.app.Application;
+import android.os.UserHandle;
+import android.util.Log;
+
+public class NfcApplication extends Application {
+
+ public static final String TAG = "NfcApplication";
+ NfcService mNfcService;
+
+ public NfcApplication() {
+
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ if (UserHandle.myUserId() == 0) {
+ mNfcService = new NfcService(this);
+ }
+ }
+}
diff --git a/src/com/android/nfc/NfcDispatcher.java b/src/com/android/nfc/NfcDispatcher.java
index b3ab97c..1721d1a 100644
--- a/src/com/android/nfc/NfcDispatcher.java
+++ b/src/com/android/nfc/NfcDispatcher.java
@@ -20,6 +20,7 @@ import com.android.nfc.RegisteredComponentCache.ComponentInfo;
import com.android.nfc.handover.HandoverManager;
import android.app.Activity;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.PendingIntent;
@@ -30,6 +31,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.nfc.NdefMessage;
@@ -38,6 +40,7 @@ import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.Log;
import java.io.FileDescriptor;
@@ -58,7 +61,6 @@ public class NfcDispatcher {
final Context mContext;
final IActivityManager mIActivityManager;
final RegisteredComponentCache mTechListFilters;
- final PackageManager mPackageManager;
final ContentResolver mContentResolver;
final HandoverManager mHandoverManager;
@@ -72,7 +74,6 @@ public class NfcDispatcher {
mIActivityManager = ActivityManagerNative.getDefault();
mTechListFilters = new RegisteredComponentCache(mContext,
NfcAdapter.ACTION_TECH_DISCOVERED, NfcAdapter.ACTION_TECH_DISCOVERED);
- mPackageManager = context.getPackageManager();
mContentResolver = context.getContentResolver();
mHandoverManager = handoverManager;
}
@@ -157,19 +158,21 @@ public class NfcDispatcher {
// is not available on Context. Instead, we query the PackageManager beforehand
// to determine if there is an Activity to handle this intent, and base the
// result of off that.
- List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
+ List<ResolveInfo> activities = packageManager.queryIntentActivitiesAsUser(intent, 0,
+ ActivityManager.getCurrentUser());
if (activities.size() > 0) {
- context.startActivity(rootIntent);
+ context.startActivityAsUser(rootIntent, UserHandle.CURRENT);
return true;
}
return false;
}
boolean tryStartActivity(Intent intentToStart) {
- List<ResolveInfo> activities = packageManager.queryIntentActivities(intentToStart, 0);
+ List<ResolveInfo> activities = packageManager.queryIntentActivitiesAsUser(
+ intentToStart, 0, ActivityManager.getCurrentUser());
if (activities.size() > 0) {
rootIntent.putExtra(NfcRootActivity.EXTRA_LAUNCH_INTENT, intentToStart);
- context.startActivity(rootIntent);
+ context.startActivityAsUser(rootIntent, UserHandle.CURRENT);
return true;
}
return false;
@@ -305,7 +308,10 @@ public class NfcDispatcher {
if (message == null) {
return false;
}
- dispatch.setNdefIntent();
+ Intent intent = dispatch.setNdefIntent();
+
+ // Bail out if the intent does not contain filterable NDEF data
+ if (intent == null) return false;
// Try to start AAR activity with matching filter
List<String> aarPackages = extractAarPackages(message);
@@ -320,7 +326,16 @@ public class NfcDispatcher {
// Try to perform regular launch of the first AAR
if (aarPackages.size() > 0) {
String firstPackage = aarPackages.get(0);
- Intent appLaunchIntent = mPackageManager.getLaunchIntentForPackage(firstPackage);
+ PackageManager pm;
+ try {
+ UserHandle currentUser = new UserHandle(ActivityManager.getCurrentUser());
+ pm = mContext.createPackageContextAsUser("android", 0,
+ currentUser).getPackageManager();
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not create user package context");
+ return false;
+ }
+ Intent appLaunchIntent = pm.getLaunchIntentForPackage(firstPackage);
if (appLaunchIntent != null && dispatch.tryStartActivity(appLaunchIntent)) {
if (DBG) Log.i(TAG, "matched AAR to application launch");
return true;
@@ -364,11 +379,20 @@ public class NfcDispatcher {
ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>();
List<ComponentInfo> registered = mTechListFilters.getComponents();
+ PackageManager pm;
+ try {
+ UserHandle currentUser = new UserHandle(ActivityManager.getCurrentUser());
+ pm = mContext.createPackageContextAsUser("android", 0,
+ currentUser).getPackageManager();
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not create user package context");
+ return false;
+ }
// Check each registered activity to see if it matches
for (ComponentInfo info : registered) {
// Don't allow wild card matching
if (filterMatch(tagTechs, info.techs) &&
- isComponentEnabled(mPackageManager, info.resolveInfo)) {
+ isComponentEnabled(pm, info.resolveInfo)) {
// Add the activity as a match if it's not already in the list
if (!matches.contains(info.resolveInfo)) {
matches.add(info.resolveInfo);
diff --git a/src/com/android/nfc/NfcRootActivity.java b/src/com/android/nfc/NfcRootActivity.java
index 1325ead..cc216f2 100644
--- a/src/com/android/nfc/NfcRootActivity.java
+++ b/src/com/android/nfc/NfcRootActivity.java
@@ -17,9 +17,11 @@
package com.android.nfc;
import android.app.Activity;
+import android.app.ActivityManager;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
+import android.os.UserHandle;
public class NfcRootActivity extends Activity {
@@ -33,7 +35,7 @@ public class NfcRootActivity extends Activity {
final Intent launchIntent = intent.getParcelableExtra(EXTRA_LAUNCH_INTENT);
if (launchIntent != null) {
try {
- startActivity(launchIntent);
+ startActivityAsUser(launchIntent, UserHandle.CURRENT);
} catch (ActivityNotFoundException e) {
}
}
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 06642f7..952b391 100755
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -23,8 +23,8 @@ import com.android.nfc.DeviceHost.LlcpSocket;
import com.android.nfc.DeviceHost.NfcDepEndpoint;
import com.android.nfc.DeviceHost.TagEndpoint;
import com.android.nfc.handover.HandoverManager;
-import com.android.nfc.nxp.NativeNfcManager;
-import com.android.nfc.nxp.NativeNfcSecureElement;
+import com.android.nfc.dhimpl.NativeNfcManager;
+import com.android.nfc.dhimpl.NativeNfcSecureElement;
import android.app.Application;
import android.app.KeyguardManager;
@@ -63,6 +63,7 @@ import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
@@ -75,7 +76,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ExecutionException;
-public class NfcService extends Application implements DeviceHostListener {
+public class NfcService implements DeviceHostListener {
private static final String ACTION_MASTER_CLEAR_NOTIFICATION = "android.intent.action.MASTER_CLEAR_NOTIFICATION";
static final boolean DBG = false;
@@ -101,8 +102,6 @@ public class NfcService extends Application implements DeviceHostListener {
static final String PREF_FIRST_BOOT = "first_boot";
static final String PREF_AIRPLANE_OVERRIDE = "airplane_override";
- static final boolean PN544_QUIRK_DISCONNECT_BEFORE_RECONFIGURE = true;
-
static final int MSG_NDEF_TAG = 0;
static final int MSG_CARD_EMULATION = 1;
static final int MSG_LLCP_LINK_ACTIVATION = 2;
@@ -114,6 +113,8 @@ public class NfcService extends Application implements DeviceHostListener {
static final int MSG_SE_APDU_RECEIVED = 10;
static final int MSG_SE_EMV_CARD_REMOVAL = 11;
static final int MSG_SE_MIFARE_ACCESS = 12;
+ static final int MSG_SE_LISTEN_ACTIVATED = 13;
+ static final int MSG_SE_LISTEN_DEACTIVATED = 14;
static final int TASK_ENABLE = 1;
static final int TASK_DISABLE = 2;
@@ -134,6 +135,15 @@ public class NfcService extends Application implements DeviceHostListener {
/** minimum screen state that enables NFC polling (discovery) */
static final int POLLING_MODE = SCREEN_STATE_ON_UNLOCKED;
+ // Time to wait for NFC controller to initialize before watchdog
+ // goes off. This time is chosen large, because firmware download
+ // may be a part of initialization.
+ static final int INIT_WATCHDOG_MS = 90000;
+
+ // Time to wait for routing to be applied before watchdog
+ // goes off
+ static final int ROUTING_WATCHDOG_MS = 10000;
+
// for use with playSound()
public static final int SOUND_START = 0;
public static final int SOUND_END = 1;
@@ -160,18 +170,10 @@ public class NfcService extends Application implements DeviceHostListener {
public static final String EXTRA_MIFARE_BLOCK =
"com.android.nfc_extras.extra.MIFARE_BLOCK";
- //TODO: dont hardcode this
- private static final byte[][] EE_WIPE_APDUS = {
- {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
- {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00,
- (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x20, (byte)0x10, (byte)0x00},
- {(byte)0x80, (byte)0xe2, (byte)0x01, (byte)0x03, (byte)0x00},
- {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
- {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x07, (byte)0xa0, (byte)0x00,
- (byte)0x00, (byte)0x04, (byte)0x76, (byte)0x30, (byte)0x30, (byte)0x00},
- {(byte)0x80, (byte)0xb4, (byte)0x00, (byte)0x00, (byte)0x00},
- {(byte)0x00, (byte)0xa4, (byte)0x04, (byte)0x00, (byte)0x00},
- };
+ public static final String ACTION_SE_LISTEN_ACTIVATED =
+ "com.android.nfc_extras.action.SE_LISTEN_ACTIVATED";
+ public static final String ACTION_SE_LISTEN_DEACTIVATED =
+ "com.android.nfc_extras.action.SE_LISTEN_DEACTIVATED";
// NFC Execution Environment
// fields below are protected by this
@@ -184,6 +186,8 @@ public class NfcService extends Application implements DeviceHostListener {
// fields below are used in multiple threads and protected by synchronized(this)
final HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
+ // mSePackages holds packages that accessed the SE, but only for the owner user,
+ // as SE access is not granted for non-owner users.
HashSet<String> mSePackages = new HashSet<String>();
int mScreenState;
boolean mIsNdefPushEnabled;
@@ -201,7 +205,9 @@ public class NfcService extends Application implements DeviceHostListener {
private DeviceHost mDeviceHost;
private SharedPreferences mPrefs;
private SharedPreferences.Editor mPrefsEditor;
- private PowerManager.WakeLock mWakeLock;
+ private PowerManager.WakeLock mRoutingWakeLock;
+ private PowerManager.WakeLock mEeWakeLock;
+
int mStartSound;
int mEndSound;
int mErrorSound;
@@ -233,6 +239,9 @@ public class NfcService extends Application implements DeviceHostListener {
throw new SecurityException(NfceeAccessControl.NFCEE_ACCESS_PATH +
" denies NFCEE access to " + pkg);
}
+ if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
+ throw new SecurityException("only the owner is allowed to call SE APIs");
+ }
}
public static NfcService getInstance() {
@@ -287,6 +296,17 @@ public class NfcService extends Application implements DeviceHostListener {
}
@Override
+ public void onSeListenActivated() {
+ sendMessage(NfcService.MSG_SE_LISTEN_ACTIVATED, null);
+ }
+
+ @Override
+ public void onSeListenDeactivated() {
+ sendMessage(NfcService.MSG_SE_LISTEN_DEACTIVATED, null);
+ }
+
+
+ @Override
public void onSeApduReceived(byte[] apdu) {
sendMessage(NfcService.MSG_SE_APDU_RECEIVED, apdu);
}
@@ -301,10 +321,7 @@ public class NfcService extends Application implements DeviceHostListener {
sendMessage(NfcService.MSG_SE_MIFARE_ACCESS, block);
}
- @Override
- public void onCreate() {
- super.onCreate();
-
+ public NfcService(Application nfcApplication) {
mNfcTagService = new TagService();
mNfcAdapter = new NfcAdapterService();
mExtrasService = new NfcAdapterExtrasService();
@@ -313,48 +330,60 @@ public class NfcService extends Application implements DeviceHostListener {
sService = this;
- mContext = this;
- mDeviceHost = new NativeNfcManager(this, this);
+ mContext = nfcApplication;
+ mDeviceHost = new NativeNfcManager(mContext, this);
HandoverManager handoverManager = new HandoverManager(mContext);
- mNfcDispatcher = new NfcDispatcher(this, handoverManager);
- mP2pLinkManager = new P2pLinkManager(mContext, handoverManager);
+ mNfcDispatcher = new NfcDispatcher(mContext, handoverManager);
+
+ mP2pLinkManager = new P2pLinkManager(mContext, handoverManager,
+ mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());
mSecureElement = new NativeNfcSecureElement(mContext);
mEeRoutingState = ROUTE_OFF;
- mNfceeAccessControl = new NfceeAccessControl(this);
+ mNfceeAccessControl = new NfceeAccessControl(mContext);
- mPrefs = getSharedPreferences(PREF, Context.MODE_PRIVATE);
+ mPrefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
mPrefsEditor = mPrefs.edit();
mState = NfcAdapter.STATE_OFF;
mIsNdefPushEnabled = mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT);
- mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
+ mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+
+ mRoutingWakeLock = mPowerManager.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mRoutingWakeLock");
+ mEeWakeLock = mPowerManager.newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, "NfcService:mEeWakeLock");
- mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "NfcService");
- mKeyguard = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
+ mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
mScreenState = checkScreenState();
ServiceManager.addService(SERVICE_NAME, mNfcAdapter);
+ // Intents only for owner
+ IntentFilter ownerFilter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
+ ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+ ownerFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+ ownerFilter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
+
+ mContext.registerReceiver(mOwnerReceiver, ownerFilter);
+
+ ownerFilter = new IntentFilter();
+ ownerFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ ownerFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ ownerFilter.addDataScheme("package");
+
+ mContext.registerReceiver(mOwnerReceiver, ownerFilter);
+
+ // Intents for all users
IntentFilter filter = new IntentFilter(NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
- filter.addAction(ACTION_MASTER_CLEAR_NOTIFICATION);
filter.addAction(Intent.ACTION_USER_PRESENT);
- filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
- filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
registerForAirplaneMode(filter);
- registerReceiver(mReceiver, filter);
-
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addDataScheme("package");
-
- registerReceiver(mReceiver, filter);
+ mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
updatePackageCache();
@@ -365,9 +394,9 @@ public class NfcService extends Application implements DeviceHostListener {
synchronized(this) {
if (mSoundPool == null) {
mSoundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0);
- mStartSound = mSoundPool.load(this, R.raw.start, 1);
- mEndSound = mSoundPool.load(this, R.raw.end, 1);
- mErrorSound = mSoundPool.load(this, R.raw.error, 1);
+ mStartSound = mSoundPool.load(mContext, R.raw.start, 1);
+ mEndSound = mSoundPool.load(mContext, R.raw.end, 1);
+ mErrorSound = mSoundPool.load(mContext, R.raw.error, 1);
}
}
}
@@ -399,8 +428,8 @@ public class NfcService extends Application implements DeviceHostListener {
}
void updatePackageCache() {
- PackageManager pm = getPackageManager();
- List<PackageInfo> packages = pm.getInstalledPackages(0);
+ PackageManager pm = mContext.getPackageManager();
+ List<PackageInfo> packages = pm.getInstalledPackages(0, UserHandle.USER_OWNER);
synchronized (this) {
mInstalledPackages = packages;
}
@@ -416,6 +445,37 @@ public class NfcService extends Application implements DeviceHostListener {
}
}
+ int doOpenSecureElementConnection() {
+ mEeWakeLock.acquire();
+ try {
+ return mSecureElement.doOpenSecureElementConnection();
+ } finally {
+ mEeWakeLock.release();
+ }
+ }
+
+ byte[] doTransceive(int handle, byte[] cmd) {
+ mEeWakeLock.acquire();
+ try {
+ return doTransceiveNoLock(handle, cmd);
+ } finally {
+ mEeWakeLock.release();
+ }
+ }
+
+ byte[] doTransceiveNoLock(int handle, byte[] cmd) {
+ return mSecureElement.doTransceive(handle, cmd);
+ }
+
+ void doDisconnect(int handle) {
+ mEeWakeLock.acquire();
+ try {
+ mSecureElement.doDisconnect(handle);
+ } finally {
+ mEeWakeLock.release();
+ }
+ }
+
/**
* Manages tasks that involve turning on/off the NFC controller.
*
@@ -512,11 +572,21 @@ public class NfcService extends Application implements DeviceHostListener {
Log.i(TAG, "Enabling NFC");
updateState(NfcAdapter.STATE_TURNING_ON);
-
- if (!mDeviceHost.initialize()) {
- Log.w(TAG, "Error enabling NFC");
- updateState(NfcAdapter.STATE_OFF);
- return false;
+ WatchDogThread watchDog = new WatchDogThread("enableInternal", INIT_WATCHDOG_MS);
+ watchDog.start();
+ try {
+ mRoutingWakeLock.acquire();
+ try {
+ if (!mDeviceHost.initialize()) {
+ Log.w(TAG, "Error enabling NFC");
+ updateState(NfcAdapter.STATE_OFF);
+ return false;
+ }
+ } finally {
+ mRoutingWakeLock.release();
+ }
+ } finally {
+ watchDog.cancel();
}
synchronized(NfcService.this) {
@@ -549,7 +619,7 @@ public class NfcService extends Application implements DeviceHostListener {
* Implemented with a new thread (instead of a Handler or AsyncTask),
* because the UI Thread and AsyncTask thread-pools can also get hung
* when the NFC controller stops responding */
- WatchDogThread watchDog = new WatchDogThread();
+ WatchDogThread watchDog = new WatchDogThread("disableInternal", ROUTING_WATCHDOG_MS);
watchDog.start();
mP2pLinkManager.enableDisable(false, false);
@@ -566,7 +636,6 @@ public class NfcService extends Application implements DeviceHostListener {
// A convenient way to stop the watchdog properly consists of
// disconnecting the tag. The polling loop shall be stopped before
// to avoid the tag being discovered again.
- applyRouting(true);
maybeDisconnectTarget();
mNfcDispatcher.setForegroundDispatch(null, null, null);
@@ -585,41 +654,64 @@ public class NfcService extends Application implements DeviceHostListener {
void executeEeWipe() {
// TODO: read SE reset list from /system/etc
- byte[][]apdus = EE_WIPE_APDUS;
+ byte[][]apdus = mDeviceHost.getWipeApdus();
+
+ if (apdus == null) {
+ Log.d(TAG, "No wipe APDUs found");
+ return;
+ }
boolean tempEnable = mState == NfcAdapter.STATE_OFF;
- if (tempEnable) {
- if (!enableInternal()) {
+ // Hold a wake-lock over the entire wipe procedure
+ mEeWakeLock.acquire();
+ try {
+ if (tempEnable && !enableInternal()) {
Log.w(TAG, "Could not enable NFC to wipe NFC-EE");
return;
}
- }
- Log.i(TAG, "Executing SE wipe");
- int handle = mSecureElement.doOpenSecureElementConnection();
- if (handle == 0) {
- Log.w(TAG, "Could not open the secure element");
- if (tempEnable) {
- disableInternal();
- }
- return;
- }
-
- mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000);
+ try {
+ // NFC enabled
+ int handle = 0;
+ try {
+ Log.i(TAG, "Executing SE wipe");
+ handle = doOpenSecureElementConnection();
+ if (handle == 0) {
+ Log.w(TAG, "Could not open the secure element");
+ return;
+ }
+ // TODO: remove this hack
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
- for (byte[] cmd : apdus) {
- byte[] resp = mSecureElement.doTransceive(handle, cmd);
- if (resp == null) {
- Log.w(TAG, "Transceive failed, could not wipe NFC-EE");
- break;
+ mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000);
+ try {
+ for (byte[] cmd : apdus) {
+ byte[] resp = doTransceiveNoLock(handle, cmd);
+ if (resp == null) {
+ Log.w(TAG, "Transceive failed, could not wipe NFC-EE");
+ break;
+ }
+ }
+ } finally {
+ mDeviceHost.resetTimeouts();
+ }
+ } finally {
+ if (handle != 0) {
+ doDisconnect(handle);
+ }
+ }
+ } finally {
+ if (tempEnable) {
+ disableInternal();
+ }
}
+ } finally {
+ mEeWakeLock.release();
}
-
- mDeviceHost.resetTimeouts();
- mSecureElement.doDisconnect(handle);
-
- if (tempEnable) {
- disableInternal();
- }
+ Log.i(TAG, "SE wipe done");
}
void updateState(int newState) {
@@ -631,7 +723,7 @@ public class NfcService extends Application implements DeviceHostListener {
Intent intent = new Intent(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(NfcAdapter.EXTRA_ADAPTER_STATE, mState);
- mContext.sendBroadcast(intent);
+ mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
}
}
}
@@ -663,12 +755,6 @@ public class NfcService extends Application implements DeviceHostListener {
}
}
- @Override
- public void onTerminate() {
- super.onTerminate();
- // NFC application is persistent, it should not be destroyed by framework
- Log.wtf(TAG, "NFC service is under attack!");
- }
final class NfcAdapterService extends INfcAdapter.Stub {
@Override
@@ -903,10 +989,6 @@ public class NfcService extends Application implements DeviceHostListener {
return ErrorCodes.ERROR_DISCONNECT;
}
- if (technology == TagTechnology.NFC_B) {
- return ErrorCodes.ERROR_NOT_SUPPORTED;
- }
-
// Note that on most tags, all technologies are behind a single
// handle. This means that the connect at the lower levels
// will do nothing, as the tag is already connected to that handle.
@@ -1234,7 +1316,7 @@ public class NfcService extends Application implements DeviceHostListener {
binder.unlinkToDeath(mOpenEe, 0);
mDeviceHost.resetTimeouts();
- mSecureElement.doDisconnect(mOpenEe.handle);
+ doDisconnect(mOpenEe.handle);
mOpenEe = null;
applyRouting(true);
@@ -1277,11 +1359,11 @@ public class NfcService extends Application implements DeviceHostListener {
throw new IOException("NFC EE already open");
}
- int handle = mSecureElement.doOpenSecureElementConnection();
+ int handle = doOpenSecureElementConnection();
if (handle == 0) {
throw new IOException("NFC EE failed to open");
}
- mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 10000);
+ mDeviceHost.setTimeout(TagTechnology.ISO_DEP, 30000);
mOpenEe = new OpenSecureElement(getCallingPid(), handle, b);
try {
@@ -1292,7 +1374,7 @@ public class NfcService extends Application implements DeviceHostListener {
// Add the calling package to the list of packages that have accessed
// the secure element.
- for (String packageName : getPackageManager().getPackagesForUid(getCallingUid())) {
+ for (String packageName : mContext.getPackageManager().getPackagesForUid(getCallingUid())) {
mSePackages.add(packageName);
}
}
@@ -1341,7 +1423,7 @@ public class NfcService extends Application implements DeviceHostListener {
}
}
- return mSecureElement.doTransceive(mOpenEe.handle, data);
+ return doTransceive(mOpenEe.handle, data);
}
@Override
@@ -1354,13 +1436,28 @@ public class NfcService extends Application implements DeviceHostListener {
public void setCardEmulationRoute(String pkg, int route) throws RemoteException {
NfcService.this.enforceNfceeAdminPerm(pkg);
mEeRoutingState = route;
- applyRouting(true);
+ ApplyRoutingTask applyRoutingTask = new ApplyRoutingTask();
+ applyRoutingTask.execute();
+ try {
+ // Block until route is set
+ applyRoutingTask.get();
+ } catch (ExecutionException e) {
+ Log.e(TAG, "failed to set card emulation mode");
+ } catch (InterruptedException e) {
+ Log.e(TAG, "failed to set card emulation mode");
+ }
}
@Override
public void authenticate(String pkg, byte[] token) throws RemoteException {
NfcService.this.enforceNfceeAdminPerm(pkg);
}
+
+ @Override
+ public String getDriverName(String pkg) throws RemoteException {
+ NfcService.this.enforceNfceeAdminPerm(pkg);
+ return mDeviceHost.getName();
+ }
}
/** resources kept while secure element is open */
@@ -1409,19 +1506,27 @@ public class NfcService extends Application implements DeviceHostListener {
class WatchDogThread extends Thread {
boolean mWatchDogCanceled = false;
+ final int mTimeout;
+
+ public WatchDogThread(String threadName, int timeout) {
+ super(threadName);
+ mTimeout = timeout;
+ }
+
@Override
public void run() {
boolean slept = false;
while (!slept) {
try {
- Thread.sleep(10000);
+ Thread.sleep(mTimeout);
slept = true;
} catch (InterruptedException e) { }
}
synchronized (this) {
if (!mWatchDogCanceled) {
// Trigger watch-dog
- Log.e(TAG, "Watch dog triggered");
+ Log.e(TAG, "Watchdog fired: name=" + getName() + " threadId=" +
+ getId() + " timeout=" + mTimeout);
mDeviceHost.doAbort();
}
}
@@ -1440,12 +1545,12 @@ public class NfcService extends Application implements DeviceHostListener {
// PN544 cannot be reconfigured while EE is open
return;
}
- WatchDogThread watchDog = new WatchDogThread();
+ WatchDogThread watchDog = new WatchDogThread("applyRouting", ROUTING_WATCHDOG_MS);
try {
watchDog.start();
- if (PN544_QUIRK_DISCONNECT_BEFORE_RECONFIGURE && mScreenState == SCREEN_STATE_OFF) {
+ if (mDeviceHost.enablePN544Quirks() && mScreenState == SCREEN_STATE_OFF) {
/* TODO undo this after the LLCP stack is fixed.
* Use a different sequence when turning the screen off to
* workaround race conditions in pn544 libnfc. The race occurs
@@ -1737,6 +1842,22 @@ public class NfcService extends Application implements DeviceHostListener {
break;
}
+ case MSG_SE_LISTEN_ACTIVATED: {
+ if (DBG) Log.d(TAG, "SE LISTEN MODE ACTIVATED");
+ Intent listenModeActivated = new Intent();
+ listenModeActivated.setAction(ACTION_SE_LISTEN_ACTIVATED);
+ sendSeBroadcast(listenModeActivated);
+ break;
+ }
+
+ case MSG_SE_LISTEN_DEACTIVATED: {
+ if (DBG) Log.d(TAG, "SE LISTEN MODE DEACTIVATED");
+ Intent listenModeDeactivated = new Intent();
+ listenModeDeactivated.setAction(ACTION_SE_LISTEN_DEACTIVATED);
+ sendSeBroadcast(listenModeDeactivated);
+ break;
+ }
+
default:
Log.e(TAG, "Unknown message received");
break;
@@ -1841,52 +1962,22 @@ public class NfcService extends Application implements DeviceHostListener {
}
mScreenState = params[0].intValue();
- boolean needWakelock = mScreenState == SCREEN_STATE_OFF;
- if (needWakelock) {
- mWakeLock.acquire();
- }
- applyRouting(false);
- if (needWakelock) {
- mWakeLock.release();
+ mRoutingWakeLock.acquire();
+ try {
+ applyRouting(false);
+ } finally {
+ mRoutingWakeLock.release();
}
return null;
}
}
}
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ private final BroadcastReceiver mOwnerReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- if (action.equals(
- NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
- // Perform applyRouting() in AsyncTask to serialize blocking calls
- new ApplyRoutingTask().execute();
- } else if (action.equals(Intent.ACTION_SCREEN_ON)
- || action.equals(Intent.ACTION_SCREEN_OFF)
- || action.equals(Intent.ACTION_USER_PRESENT)) {
- // Perform applyRouting() in AsyncTask to serialize blocking calls
- int screenState = SCREEN_STATE_OFF;
- if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- screenState = SCREEN_STATE_OFF;
- } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
- screenState = mKeyguard.isKeyguardLocked() ?
- SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED;
- } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
- screenState = SCREEN_STATE_ON_UNLOCKED;
- }
- new ApplyRoutingTask().execute(Integer.valueOf(screenState));
- } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
- EnableDisableTask eeWipeTask = new EnableDisableTask();
- eeWipeTask.execute(TASK_EE_WIPE);
- try {
- eeWipeTask.get(); // blocks until EE wipe is complete
- } catch (ExecutionException e) {
- Log.w(TAG, "failed to wipe NFC-EE");
- } catch (InterruptedException e) {
- Log.w(TAG, "failed to wipe NFC-EE");
- }
- } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
+ if (action.equals(Intent.ACTION_PACKAGE_REMOVED) ||
action.equals(Intent.ACTION_PACKAGE_ADDED) ||
action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE) ||
action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
@@ -1910,6 +2001,42 @@ public class NfcService extends Application implements DeviceHostListener {
}
}
}
+ } else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
+ EnableDisableTask eeWipeTask = new EnableDisableTask();
+ eeWipeTask.execute(TASK_EE_WIPE);
+ try {
+ eeWipeTask.get(); // blocks until EE wipe is complete
+ } catch (ExecutionException e) {
+ Log.w(TAG, "failed to wipe NFC-EE");
+ } catch (InterruptedException e) {
+ Log.w(TAG, "failed to wipe NFC-EE");
+ }
+ }
+ }
+ };
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(
+ NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
+ // Perform applyRouting() in AsyncTask to serialize blocking calls
+ new ApplyRoutingTask().execute();
+ } else if (action.equals(Intent.ACTION_SCREEN_ON)
+ || action.equals(Intent.ACTION_SCREEN_OFF)
+ || action.equals(Intent.ACTION_USER_PRESENT)) {
+ // Perform applyRouting() in AsyncTask to serialize blocking calls
+ int screenState = SCREEN_STATE_OFF;
+ if (action.equals(Intent.ACTION_SCREEN_OFF)) {
+ screenState = SCREEN_STATE_OFF;
+ } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
+ screenState = mKeyguard.isKeyguardLocked() ?
+ SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED;
+ } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
+ screenState = SCREEN_STATE_ON_UNLOCKED;
+ }
+ new ApplyRoutingTask().execute(Integer.valueOf(screenState));
} else if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
// Query the airplane mode from Settings.System just to make sure that
diff --git a/src/com/android/nfc/P2pEventManager.java b/src/com/android/nfc/P2pEventManager.java
index c024afc..68f479b 100644
--- a/src/com/android/nfc/P2pEventManager.java
+++ b/src/com/android/nfc/P2pEventManager.java
@@ -51,7 +51,16 @@ public class P2pEventManager implements P2pEventListener, SendUi.Callback {
Context.NOTIFICATION_SERVICE);
mSending = false;
- mSendUi = new SendUi(context, this);
+ final int uiModeType = mContext.getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_TYPE_MASK;
+ if (uiModeType == Configuration.UI_MODE_TYPE_APPLIANCE) {
+ // "Appliances" don't intrinsically have a way of confirming this, so we
+ // don't use the UI and just autoconfirm where necessary.
+ // Don't instantiate SendUi or else we'll use memory and never reclaim it.
+ mSendUi = null;
+ } else {
+ mSendUi = new SendUi(context, this);
+ }
}
@Override
@@ -61,19 +70,17 @@ public class P2pEventManager implements P2pEventListener, SendUi.Callback {
mNdefReceived = false;
mVibrator.vibrate(VIBRATION_PATTERN, -1);
- mSendUi.takeScreenshot();
+ if (mSendUi != null) {
+ mSendUi.takeScreenshot();
+ }
}
@Override
public void onP2pSendConfirmationRequested() {
- final int uiModeType = mContext.getResources().getConfiguration().uiMode
- & Configuration.UI_MODE_TYPE_MASK;
- if (uiModeType == Configuration.UI_MODE_TYPE_APPLIANCE) {
- // "Appliances" don't intrinsically have a way of confirming this, so we
- // will just auto-confirm.
- mCallback.onP2pSendConfirmed();
- } else {
+ if (mSendUi != null) {
mSendUi.showPreSend();
+ } else {
+ mCallback.onP2pSendConfirmed();
}
}
@@ -81,7 +88,9 @@ public class P2pEventManager implements P2pEventListener, SendUi.Callback {
public void onP2pSendComplete() {
mNfcService.playSound(NfcService.SOUND_END);
mVibrator.vibrate(VIBRATION_PATTERN, -1);
- mSendUi.finish(SendUi.FINISH_SEND_SUCCESS);
+ if (mSendUi != null) {
+ mSendUi.finish(SendUi.FINISH_SEND_SUCCESS);
+ }
mSending = false;
mNdefSent = true;
}
@@ -100,14 +109,16 @@ public class P2pEventManager implements P2pEventListener, SendUi.Callback {
public void onP2pReceiveComplete(boolean playSound) {
mVibrator.vibrate(VIBRATION_PATTERN, -1);
if (playSound) mNfcService.playSound(NfcService.SOUND_END);
- // TODO we still don't have a nice receive solution
- // The sanest solution right now is just to scale back up what we had
- // and start the new activity. It is not perfect, but at least it is
- // consistent behavior. All other variants involve making the old
- // activity screenshot disappear, and then removing the animation
- // window hoping the new activity has started by then. This just goes
- // wrong too often and can look weird.
- mSendUi.finish(SendUi.FINISH_SCALE_UP);
+ if (mSendUi != null) {
+ // TODO we still don't have a nice receive solution
+ // The sanest solution right now is just to scale back up what we had
+ // and start the new activity. It is not perfect, but at least it is
+ // consistent behavior. All other variants involve making the old
+ // activity screenshot disappear, and then removing the animation
+ // window hoping the new activity has started by then. This just goes
+ // wrong too often and can look weird.
+ mSendUi.finish(SendUi.FINISH_SCALE_UP);
+ }
mNdefReceived = true;
}
@@ -117,7 +128,7 @@ public class P2pEventManager implements P2pEventListener, SendUi.Callback {
mNfcService.playSound(NfcService.SOUND_ERROR);
mSending = false;
}
- if (!mNdefSent && !mNdefReceived) {
+ if (!mNdefSent && !mNdefReceived && mSendUi != null) {
mSendUi.finish(SendUi.FINISH_SCALE_UP);
}
}
@@ -125,7 +136,9 @@ public class P2pEventManager implements P2pEventListener, SendUi.Callback {
@Override
public void onSendConfirmed() {
if (!mSending) {
- mSendUi.showStartSend();
+ if (mSendUi != null) {
+ mSendUi.showStartSend();
+ }
mCallback.onP2pSendConfirmed();
}
mSending = true;
diff --git a/src/com/android/nfc/P2pLinkManager.java b/src/com/android/nfc/P2pLinkManager.java
index 253ddaf..9b23f65 100755
--- a/src/com/android/nfc/P2pLinkManager.java
+++ b/src/com/android/nfc/P2pLinkManager.java
@@ -167,6 +167,9 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba
final Handler mHandler;
final HandoverManager mHandoverManager;
+ final int mDefaultMiu;
+ final int mDefaultRwSize;
+
// Locked on NdefP2pManager.this
int mLinkState;
int mSendState; // valid during LINK_STATE_UP or LINK_STATE_DEBOUNCE
@@ -179,9 +182,10 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba
SharedPreferences mPrefs;
boolean mFirstBeam;
- public P2pLinkManager(Context context, HandoverManager handoverManager) {
+ public P2pLinkManager(Context context, HandoverManager handoverManager, int defaultMiu,
+ int defaultRwSize) {
mNdefPushServer = new NdefPushServer(NDEFPUSH_SAP, mNppCallback);
- mDefaultSnepServer = new SnepServer(mDefaultSnepCallback);
+ mDefaultSnepServer = new SnepServer(mDefaultSnepCallback, defaultMiu, defaultRwSize);
mHandoverServer = new HandoverServer(HANDOVER_SAP, handoverManager, mHandoverCallback);
if (ECHOSERVER_ENABLED) {
@@ -201,6 +205,8 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba
mPrefs = context.getSharedPreferences(NfcService.PREF, Context.MODE_PRIVATE);
mFirstBeam = mPrefs.getBoolean(NfcService.PREF_FIRST_BEAM, true);
mHandoverManager = handoverManager;
+ mDefaultMiu = defaultMiu;
+ mDefaultRwSize = defaultRwSize;
}
/**
@@ -417,11 +423,11 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba
long time = SystemClock.elapsedRealtime();
-
try {
if (DBG) Log.d(TAG, "Sending ndef via SNEP");
- int snepResult = doSnepProtocol(mHandoverManager, m, uris);
+ int snepResult = doSnepProtocol(mHandoverManager, m, uris,
+ mDefaultMiu, mDefaultRwSize);
switch (snepResult) {
case SNEP_HANDOVER_UNSUPPORTED:
@@ -461,8 +467,8 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba
}
static int doSnepProtocol(HandoverManager handoverManager,
- NdefMessage msg, Uri[] uris) throws IOException {
- SnepClient snepClient = new SnepClient();
+ NdefMessage msg, Uri[] uris, int miu, int rwSize) throws IOException {
+ SnepClient snepClient = new SnepClient(miu, rwSize);
try {
snepClient.connect();
} catch (IOException e) {
diff --git a/src/com/android/nfc/RegisteredComponentCache.java b/src/com/android/nfc/RegisteredComponentCache.java
index 1bac283..5da2cd4 100644
--- a/src/com/android/nfc/RegisteredComponentCache.java
+++ b/src/com/android/nfc/RegisteredComponentCache.java
@@ -19,6 +19,7 @@ package com.android.nfc;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -29,6 +30,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
+import android.os.UserHandle;
import android.util.Log;
import java.io.IOException;
@@ -69,12 +71,16 @@ public class RegisteredComponentCache {
intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
- mContext.registerReceiver(receiver, intentFilter);
+ mContext.registerReceiverAsUser(receiver, UserHandle.ALL, intentFilter, null, null);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- mContext.registerReceiver(receiver, sdFilter);
+ mContext.registerReceiverAsUser(receiver, UserHandle.ALL, sdFilter, null, null);
+ // Generate a new list upon switching users as well
+ IntentFilter userFilter = new IntentFilter();
+ userFilter.addAction(Intent.ACTION_USER_SWITCHED);
+ mContext.registerReceiverAsUser(receiver, UserHandle.ALL, userFilter, null, null);
}
public static class ComponentInfo {
@@ -137,13 +143,21 @@ public class RegisteredComponentCache {
}
void generateComponentsList() {
- PackageManager pm = mContext.getPackageManager();
+ PackageManager pm;
+ try {
+ UserHandle currentUser = new UserHandle(ActivityManager.getCurrentUser());
+ pm = mContext.createPackageContextAsUser("android", 0,
+ currentUser).getPackageManager();
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not create user package context");
+ return;
+ }
ArrayList<ComponentInfo> components = new ArrayList<ComponentInfo>();
- List<ResolveInfo> resolveInfos = pm.queryIntentActivities(new Intent(mAction),
- PackageManager.GET_META_DATA);
+ List<ResolveInfo> resolveInfos = pm.queryIntentActivitiesAsUser(new Intent(mAction),
+ PackageManager.GET_META_DATA, ActivityManager.getCurrentUser());
for (ResolveInfo resolveInfo : resolveInfos) {
try {
- parseComponentInfo(resolveInfo, components);
+ parseComponentInfo(pm, resolveInfo, components);
} catch (XmlPullParserException e) {
Log.w(TAG, "Unable to load component info " + resolveInfo.toString(), e);
} catch (IOException e) {
@@ -158,10 +172,9 @@ public class RegisteredComponentCache {
}
}
- void parseComponentInfo(ResolveInfo info, ArrayList<ComponentInfo> components)
- throws XmlPullParserException, IOException {
+ void parseComponentInfo(PackageManager pm, ResolveInfo info,
+ ArrayList<ComponentInfo> components) throws XmlPullParserException, IOException {
ActivityInfo ai = info.activityInfo;
- PackageManager pm = mContext.getPackageManager();
XmlResourceParser parser = null;
try {
diff --git a/src/com/android/nfc/SendUi.java b/src/com/android/nfc/SendUi.java
index 23602c9..5b5c234 100644
--- a/src/com/android/nfc/SendUi.java
+++ b/src/com/android/nfc/SendUi.java
@@ -183,7 +183,7 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener,
// We're only allowed to use hardware acceleration if
// isHighEndGfx() returns true - otherwise, we're too limited
// on resources to do it.
- mHardwareAccelerated = ActivityManager.isHighEndGfx(mDisplay);
+ mHardwareAccelerated = ActivityManager.isHighEndGfx();
int hwAccelerationFlags = mHardwareAccelerated ?
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED : 0;
@@ -194,6 +194,8 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener,
| hwAccelerationFlags
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
PixelFormat.OPAQUE);
+ mWindowLayoutParams.privateFlags |=
+ WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
mWindowLayoutParams.token = new Binder();
mFrameCounterAnimator = new TimeAnimator();
@@ -443,6 +445,9 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener,
// Navbar has different sizes, depending on orientation
final int navBarHeight = hasNavBar ? mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_height) : 0;
+ final int navBarHeightLandscape = hasNavBar ? mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height_landscape) : 0;
+
final int navBarWidth = hasNavBar ? mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_width) : 0;
@@ -483,13 +488,20 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener,
int newTop = statusBarHeight;
int newWidth = bitmap.getWidth();
int newHeight = bitmap.getHeight();
+ float smallestWidth = (float)Math.min(newWidth, newHeight);
+ float smallestWidthDp = smallestWidth / (mDisplayMetrics.densityDpi / 160f);
if (bitmap.getWidth() < bitmap.getHeight()) {
// Portrait mode: status bar is at the top, navbar bottom, width unchanged
newHeight = bitmap.getHeight() - statusBarHeight - navBarHeight;
} else {
- // Landscape mode: status bar is at the top, navbar right
- newHeight = bitmap.getHeight() - statusBarHeight;
- newWidth = bitmap.getWidth() - navBarWidth;
+ // Landscape mode: status bar is at the top
+ // Navbar: bottom on >599dp width devices, otherwise to the side
+ if (smallestWidthDp > 599) {
+ newHeight = bitmap.getHeight() - statusBarHeight - navBarHeightLandscape;
+ } else {
+ newHeight = bitmap.getHeight() - statusBarHeight;
+ newWidth = bitmap.getWidth() - navBarWidth;
+ }
}
bitmap = Bitmap.createBitmap(bitmap, newLeft, newTop, newWidth, newHeight);
diff --git a/src/com/android/nfc/handover/BluetoothHeadsetHandover.java b/src/com/android/nfc/handover/BluetoothHeadsetHandover.java
index 7974dfa..1377160 100644
--- a/src/com/android/nfc/handover/BluetoothHeadsetHandover.java
+++ b/src/com/android/nfc/handover/BluetoothHeadsetHandover.java
@@ -16,6 +16,7 @@
package com.android.nfc.handover;
+import android.app.ActivityManager;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -28,6 +29,7 @@ import android.content.IntentFilter;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.UserHandle;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Toast;
@@ -44,9 +46,8 @@ import com.android.nfc.R;
* designed to be re-used after the sequence has completed or timed out.
* Subsequent NFC interactions should use new objects.
*
- * TODO: UI review
*/
-public class BluetoothHeadsetHandover {
+public class BluetoothHeadsetHandover implements BluetoothProfile.ServiceListener {
static final String TAG = HandoverManager.TAG;
static final boolean DBG = HandoverManager.DBG;
@@ -57,28 +58,33 @@ public class BluetoothHeadsetHandover {
static final int STATE_INIT = 0;
static final int STATE_TURNING_ON = 1;
- static final int STATE_WAITING_FOR_BOND_CONFIRMATION = 2;
- static final int STATE_BONDING = 3;
- static final int STATE_CONNECTING = 4;
- static final int STATE_DISCONNECTING = 5;
- static final int STATE_COMPLETE = 6;
+ static final int STATE_WAITING_FOR_PROXIES = 2;
+ static final int STATE_INIT_COMPLETE = 3;
+ static final int STATE_WAITING_FOR_BOND_CONFIRMATION = 4;
+ static final int STATE_BONDING = 5;
+ static final int STATE_CONNECTING = 6;
+ static final int STATE_DISCONNECTING = 7;
+ static final int STATE_COMPLETE = 8;
static final int RESULT_PENDING = 0;
static final int RESULT_CONNECTED = 1;
static final int RESULT_DISCONNECTED = 2;
+ static final int ACTION_INIT = 0;
static final int ACTION_DISCONNECT = 1;
static final int ACTION_CONNECT = 2;
static final int MSG_TIMEOUT = 1;
+ static final int MSG_NEXT_STEP = 2;
final Context mContext;
final BluetoothDevice mDevice;
final String mName;
final HandoverPowerManager mHandoverPowerManager;
- final BluetoothA2dp mA2dp;
- final BluetoothHeadset mHeadset;
final Callback mCallback;
+ final BluetoothAdapter mBluetoothAdapter;
+
+ final Object mLock = new Object();
// only used on main thread
int mAction;
@@ -86,21 +92,24 @@ public class BluetoothHeadsetHandover {
int mHfpResult; // used only in STATE_CONNECTING and STATE_DISCONNETING
int mA2dpResult; // used only in STATE_CONNECTING and STATE_DISCONNETING
+ // protected by mLock
+ BluetoothA2dp mA2dp;
+ BluetoothHeadset mHeadset;
+
public interface Callback {
public void onBluetoothHeadsetHandoverComplete(boolean connected);
}
public BluetoothHeadsetHandover(Context context, BluetoothDevice device, String name,
- HandoverPowerManager powerManager, BluetoothA2dp a2dp, BluetoothHeadset headset,
- Callback callback) {
+ HandoverPowerManager powerManager, Callback callback) {
checkMainThread(); // mHandler must get get constructed on Main Thread for toasts to work
mContext = context;
mDevice = device;
mName = name;
mHandoverPowerManager = powerManager;
- mA2dp = a2dp;
- mHeadset = headset;
mCallback = callback;
+ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+
mState = STATE_INIT;
}
@@ -111,6 +120,7 @@ public class BluetoothHeadsetHandover {
public void start() {
checkMainThread();
if (mState != STATE_INIT) return;
+ if (mBluetoothAdapter == null) return;
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
@@ -122,15 +132,8 @@ public class BluetoothHeadsetHandover {
mContext.registerReceiver(mReceiver, filter);
- if (mA2dp.getConnectedDevices().contains(mDevice) ||
- mHeadset.getConnectedDevices().contains(mDevice)) {
- Log.i(TAG, "ACTION_DISCONNECT addr=" + mDevice + " name=" + mName);
- mAction = ACTION_DISCONNECT;
- } else {
- Log.i(TAG, "ACTION_CONNECT addr=" + mDevice + " name=" + mName);
- mAction = ACTION_CONNECT;
- }
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TIMEOUT), TIMEOUT_MS);
+ mAction = ACTION_INIT;
nextStep();
}
@@ -138,35 +141,83 @@ public class BluetoothHeadsetHandover {
* Called to execute next step in state machine
*/
void nextStep() {
- if (mAction == ACTION_CONNECT) {
+ if (mAction == ACTION_INIT) {
+ nextStepInit();
+ } else if (mAction == ACTION_CONNECT) {
nextStepConnect();
} else {
nextStepDisconnect();
}
}
- void nextStepDisconnect() {
+ /*
+ * Enables bluetooth and gets the profile proxies
+ */
+ void nextStepInit() {
switch (mState) {
case STATE_INIT:
- mState = STATE_DISCONNECTING;
- if (mHeadset.getConnectionState(mDevice) != BluetoothProfile.STATE_DISCONNECTED) {
- mHfpResult = RESULT_PENDING;
- mHeadset.disconnect(mDevice);
- } else {
- mHfpResult = RESULT_DISCONNECTED;
- }
- if (mA2dp.getConnectionState(mDevice) != BluetoothProfile.STATE_DISCONNECTED) {
- mA2dpResult = RESULT_PENDING;
- mA2dp.disconnect(mDevice);
- } else {
- mA2dpResult = RESULT_DISCONNECTED;
+ if (!mHandoverPowerManager.isBluetoothEnabled()) {
+ if (mHandoverPowerManager.enableBluetooth()) {
+ // Bluetooth is being enabled
+ mState = STATE_TURNING_ON;
+ } else {
+ toast(mContext.getString(R.string.failed_to_enable_bt));
+ complete(false);
+ }
+ break;
}
- if (mA2dpResult == RESULT_PENDING || mHfpResult == RESULT_PENDING) {
- toast(mContext.getString(R.string.disconnecting_headset ) + " " +
- mName + "...");
+ // fall-through
+ case STATE_TURNING_ON:
+ if (mA2dp == null || mHeadset == null) {
+ mState = STATE_WAITING_FOR_PROXIES;
+ if (!getProfileProxys()) {
+ complete(false);
+ }
break;
}
// fall-through
+ case STATE_WAITING_FOR_PROXIES:
+ mState = STATE_INIT_COMPLETE;
+ // Check connected devices and see if we need to disconnect
+ synchronized(mLock) {
+ if (mA2dp.getConnectedDevices().contains(mDevice) ||
+ mHeadset.getConnectedDevices().contains(mDevice)) {
+ Log.i(TAG, "ACTION_DISCONNECT addr=" + mDevice + " name=" + mName);
+ mAction = ACTION_DISCONNECT;
+ } else {
+ Log.i(TAG, "ACTION_CONNECT addr=" + mDevice + " name=" + mName);
+ mAction = ACTION_CONNECT;
+ }
+ }
+ nextStep();
+ }
+
+ }
+
+ void nextStepDisconnect() {
+ switch (mState) {
+ case STATE_INIT_COMPLETE:
+ mState = STATE_DISCONNECTING;
+ synchronized (mLock) {
+ if (mHeadset.getConnectionState(mDevice) != BluetoothProfile.STATE_DISCONNECTED) {
+ mHfpResult = RESULT_PENDING;
+ mHeadset.disconnect(mDevice);
+ } else {
+ mHfpResult = RESULT_DISCONNECTED;
+ }
+ if (mA2dp.getConnectionState(mDevice) != BluetoothProfile.STATE_DISCONNECTED) {
+ mA2dpResult = RESULT_PENDING;
+ mA2dp.disconnect(mDevice);
+ } else {
+ mA2dpResult = RESULT_DISCONNECTED;
+ }
+ if (mA2dpResult == RESULT_PENDING || mHfpResult == RESULT_PENDING) {
+ toast(mContext.getString(R.string.disconnecting_headset ) + " " +
+ mName + "...");
+ break;
+ }
+ }
+ // fall-through
case STATE_DISCONNECTING:
if (mA2dpResult == RESULT_PENDING || mHfpResult == RESULT_PENDING) {
// still disconnecting
@@ -178,26 +229,26 @@ public class BluetoothHeadsetHandover {
complete(false);
break;
}
+
+ }
+
+ boolean getProfileProxys() {
+ if(!mBluetoothAdapter.getProfileProxy(mContext, this, BluetoothProfile.HEADSET))
+ return false;
+
+ if(!mBluetoothAdapter.getProfileProxy(mContext, this, BluetoothProfile.A2DP))
+ return false;
+
+ return true;
}
void nextStepConnect() {
switch (mState) {
- case STATE_INIT:
- if (!mHandoverPowerManager.isBluetoothEnabled()) {
- if (mHandoverPowerManager.enableBluetooth()) {
- // Bluetooth is being enabled
- mState = STATE_TURNING_ON;
- } else {
- toast(mContext.getString(R.string.failed_to_enable_bt));
- complete(false);
- }
- break;
- }
- // fall-through
- case STATE_TURNING_ON:
+ case STATE_INIT_COMPLETE:
if (mDevice.getBondState() != BluetoothDevice.BOND_BONDED) {
requestPairConfirmation();
mState = STATE_WAITING_FOR_BOND_CONFIRMATION;
+
break;
}
// fall-through
@@ -211,21 +262,23 @@ public class BluetoothHeadsetHandover {
// Bluetooth Profile service will correctly serialize
// HFP then A2DP connect
mState = STATE_CONNECTING;
- if (mHeadset.getConnectionState(mDevice) != BluetoothProfile.STATE_CONNECTED) {
- mHfpResult = RESULT_PENDING;
- mHeadset.connect(mDevice);
- } else {
- mHfpResult = RESULT_CONNECTED;
- }
- if (mA2dp.getConnectionState(mDevice) != BluetoothProfile.STATE_CONNECTED) {
- mA2dpResult = RESULT_PENDING;
- mA2dp.connect(mDevice);
- } else {
- mA2dpResult = RESULT_CONNECTED;
- }
- if (mA2dpResult == RESULT_PENDING || mHfpResult == RESULT_PENDING) {
- toast(mContext.getString(R.string.connecting_headset) + " " + mName + "...");
- break;
+ synchronized (mLock) {
+ if (mHeadset.getConnectionState(mDevice) != BluetoothProfile.STATE_CONNECTED) {
+ mHfpResult = RESULT_PENDING;
+ mHeadset.connect(mDevice);
+ } else {
+ mHfpResult = RESULT_CONNECTED;
+ }
+ if (mA2dp.getConnectionState(mDevice) != BluetoothProfile.STATE_CONNECTED) {
+ mA2dpResult = RESULT_PENDING;
+ mA2dp.connect(mDevice);
+ } else {
+ mA2dpResult = RESULT_CONNECTED;
+ }
+ if (mA2dpResult == RESULT_PENDING || mHfpResult == RESULT_PENDING) {
+ toast(mContext.getString(R.string.connecting_headset) + " " + mName + "...");
+ break;
+ }
}
// fall-through
case STATE_CONNECTING:
@@ -260,7 +313,7 @@ public class BluetoothHeadsetHandover {
if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action) && mState == STATE_TURNING_ON) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
if (state == BluetoothAdapter.STATE_ON) {
- nextStepConnect();
+ nextStep();
} else if (state == BluetoothAdapter.STATE_OFF) {
toast(mContext.getString(R.string.failed_to_enable_bt));
complete(false);
@@ -313,6 +366,16 @@ public class BluetoothHeadsetHandover {
mState = STATE_COMPLETE;
mContext.unregisterReceiver(mReceiver);
mHandler.removeMessages(MSG_TIMEOUT);
+ synchronized (mLock) {
+ if (mA2dp != null) {
+ mBluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, mA2dp);
+ }
+ if (mHeadset != null) {
+ mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadset);
+ }
+ mA2dp = null;
+ mHeadset = null;
+ }
mCallback.onBluetoothHeadsetHandoverComplete(connected);
}
@@ -324,10 +387,10 @@ public class BluetoothHeadsetHandover {
Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_MEDIA_PLAY));
- mContext.sendOrderedBroadcast(intent, null);
+ mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null, null, null, 0, null, null);
intent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_MEDIA_PLAY));
- mContext.sendOrderedBroadcast(intent, null);
+ mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null, null, null, 0, null, null);
}
void requestPairConfirmation() {
@@ -336,7 +399,7 @@ public class BluetoothHeadsetHandover {
dialogIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
- mContext.startActivity(dialogIntent);
+ mContext.startActivityAsUser(dialogIntent, new UserHandle(UserHandle.USER_CURRENT));
}
final Handler mHandler = new Handler() {
@@ -348,6 +411,9 @@ public class BluetoothHeadsetHandover {
Log.i(TAG, "Timeout completing BT handover");
complete(false);
break;
+ case MSG_NEXT_STEP:
+ nextStep();
+ break;
}
}
};
@@ -364,4 +430,29 @@ public class BluetoothHeadsetHandover {
throw new IllegalThreadStateException("must be called on main thread");
}
}
+
+ @Override
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ synchronized (mLock) {
+ switch (profile) {
+ case BluetoothProfile.HEADSET:
+ mHeadset = (BluetoothHeadset) proxy;
+ if (mA2dp != null) {
+ mHandler.sendEmptyMessage(MSG_NEXT_STEP);
+ }
+ break;
+ case BluetoothProfile.A2DP:
+ mA2dp = (BluetoothA2dp) proxy;
+ if (mHeadset != null) {
+ mHandler.sendEmptyMessage(MSG_NEXT_STEP);
+ }
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(int profile) {
+ // We can ignore these
+ }
}
diff --git a/src/com/android/nfc/handover/HandoverManager.java b/src/com/android/nfc/handover/HandoverManager.java
index f77f780..e7e807d 100644
--- a/src/com/android/nfc/handover/HandoverManager.java
+++ b/src/com/android/nfc/handover/HandoverManager.java
@@ -33,11 +33,8 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Notification.Builder;
-import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -52,6 +49,7 @@ import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;
@@ -62,8 +60,7 @@ import com.android.nfc.R;
/**
* Manages handover of NFC to other technologies.
*/
-public class HandoverManager implements BluetoothProfile.ServiceListener,
- BluetoothHeadsetHandover.Callback {
+public class HandoverManager implements BluetoothHeadsetHandover.Callback {
static final String TAG = "NfcHandover";
static final boolean DBG = true;
@@ -142,8 +139,6 @@ public class HandoverManager implements BluetoothProfile.ServiceListener,
// Variables below synchronized on HandoverManager.this
final HashMap<Pair<String, Boolean>, HandoverTransfer> mTransfers;
- BluetoothHeadset mBluetoothHeadset;
- BluetoothA2dp mBluetoothA2dp;
BluetoothHeadsetHandover mBluetoothHeadsetHandover;
boolean mBluetoothHeadsetConnected;
@@ -390,7 +385,8 @@ public class HandoverManager implements BluetoothProfile.ServiceListener,
notBuilder.setContentText(mContext.getString(R.string.beam_touch_to_view));
Intent viewIntent = buildViewIntent();
- PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, viewIntent, 0);
+ PendingIntent contentIntent = PendingIntent.getActivityAsUser(
+ mContext, 0, viewIntent, 0, null, UserHandle.CURRENT);
notBuilder.setContentIntent(contentIntent);
@@ -410,7 +406,8 @@ public class HandoverManager implements BluetoothProfile.ServiceListener,
return;
}
- mNotificationManager.notify(mNotificationId, notBuilder.build());
+ mNotificationManager.notifyAsUser(null, mNotificationId, notBuilder.build(),
+ UserHandle.CURRENT);
}
synchronized void updateStateAndNotification(int newState) {
@@ -537,7 +534,7 @@ public class HandoverManager implements BluetoothProfile.ServiceListener,
Uri uri = mediaUri != null ? mediaUri :
Uri.parse(ContentResolver.SCHEME_FILE + "://" + filePath);
viewIntent.setDataAndTypeAndNormalize(uri, mimeTypes.get(filePath));
-
+ viewIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return viewIntent;
}
@@ -612,10 +609,6 @@ public class HandoverManager implements BluetoothProfile.ServiceListener,
public HandoverManager(Context context) {
mContext = context;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- if (mBluetoothAdapter != null) {
- mBluetoothAdapter.getProfileProxy(mContext, this, BluetoothProfile.HEADSET);
- mBluetoothAdapter.getProfileProxy(mContext, this, BluetoothProfile.A2DP);
- }
mNotificationManager = (NotificationManager) mContext.getSystemService(
Context.NOTIFICATION_SERVICE);
@@ -792,9 +785,7 @@ public class HandoverManager implements BluetoothProfile.ServiceListener,
if (!handover.valid) return true;
synchronized (HandoverManager.this) {
- if (mBluetoothAdapter == null ||
- mBluetoothA2dp == null ||
- mBluetoothHeadset == null) {
+ if (mBluetoothAdapter == null) {
if (DBG) Log.d(TAG, "BT handover, but BT not available");
return true;
}
@@ -803,7 +794,7 @@ public class HandoverManager implements BluetoothProfile.ServiceListener,
return true;
}
mBluetoothHeadsetHandover = new BluetoothHeadsetHandover(mContext, handover.device,
- handover.name, mHandoverPowerManager, mBluetoothA2dp, mBluetoothHeadset, this);
+ handover.name, mHandoverPowerManager, this);
mBluetoothHeadsetHandover.start();
}
return true;
@@ -983,34 +974,6 @@ public class HandoverManager implements BluetoothProfile.ServiceListener,
}
@Override
- public void onServiceConnected(int profile, BluetoothProfile proxy) {
- synchronized (HandoverManager.this) {
- switch (profile) {
- case BluetoothProfile.HEADSET:
- mBluetoothHeadset = (BluetoothHeadset) proxy;
- break;
- case BluetoothProfile.A2DP:
- mBluetoothA2dp = (BluetoothA2dp) proxy;
- break;
- }
- }
- }
-
- @Override
- public void onServiceDisconnected(int profile) {
- synchronized (HandoverManager.this) {
- switch (profile) {
- case BluetoothProfile.HEADSET:
- mBluetoothHeadset = null;
- break;
- case BluetoothProfile.A2DP:
- mBluetoothA2dp = null;
- break;
- }
- }
- }
-
- @Override
public void onBluetoothHeadsetHandoverComplete(boolean connected) {
synchronized (HandoverManager.this) {
mBluetoothHeadsetHandover = null;
diff --git a/src/com/android/nfc/ndefpush/NdefPushServer.java b/src/com/android/nfc/ndefpush/NdefPushServer.java
index ca58a67..bf92c17 100755
--- a/src/com/android/nfc/ndefpush/NdefPushServer.java
+++ b/src/com/android/nfc/ndefpush/NdefPushServer.java
@@ -117,28 +117,49 @@ public class NdefPushServer {
/** Server class, used to listen for incoming connection request */
class ServerThread extends Thread {
+ // Variables below synchronized on NdefPushServer.this
boolean mRunning = true;
LlcpServerSocket mServerSocket;
@Override
public void run() {
- while (mRunning) {
+ boolean threadRunning;
+ synchronized (NdefPushServer.this) {
+ threadRunning = mRunning;
+ }
+ while (threadRunning) {
if (DBG) Log.d(TAG, "about create LLCP service socket");
try {
- mServerSocket = mService.createLlcpServerSocket(mSap, SERVICE_NAME,
- MIU, 1, 1024);
+ synchronized (NdefPushServer.this) {
+ mServerSocket = mService.createLlcpServerSocket(mSap, SERVICE_NAME,
+ MIU, 1, 1024);
+ }
if (mServerSocket == null) {
if (DBG) Log.d(TAG, "failed to create LLCP service socket");
return;
}
if (DBG) Log.d(TAG, "created LLCP service socket");
- while (mRunning) {
+ synchronized (NdefPushServer.this) {
+ threadRunning = mRunning;
+ }
+
+ while (threadRunning) {
+ LlcpServerSocket serverSocket;
+ synchronized (NdefPushServer.this) {
+ serverSocket = mServerSocket;
+ }
+ if (serverSocket == null) return;
+
if (DBG) Log.d(TAG, "about to accept");
- LlcpSocket communicationSocket = mServerSocket.accept();
+ LlcpSocket communicationSocket = serverSocket.accept();
if (DBG) Log.d(TAG, "accept returned " + communicationSocket);
if (communicationSocket != null) {
new ConnectionThread(communicationSocket).start();
}
+
+ synchronized (NdefPushServer.this) {
+ threadRunning = mRunning;
+ }
}
if (DBG) Log.d(TAG, "stop running");
} catch (LlcpException e) {
@@ -146,28 +167,36 @@ public class NdefPushServer {
} catch (IOException e) {
Log.e(TAG, "IO error", e);
} finally {
- if (mServerSocket != null) {
- if (DBG) Log.d(TAG, "about to close");
- try {
- mServerSocket.close();
- } catch (IOException e) {
- // ignore
+ synchronized (NdefPushServer.this) {
+ if (mServerSocket != null) {
+ if (DBG) Log.d(TAG, "about to close");
+ try {
+ mServerSocket.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ mServerSocket = null;
}
- mServerSocket = null;
}
}
+
+ synchronized (NdefPushServer.this) {
+ threadRunning = mRunning;
+ }
}
}
public void shutdown() {
- mRunning = false;
- if (mServerSocket != null) {
- try {
- mServerSocket.close();
- } catch (IOException e) {
- // ignore
+ synchronized (NdefPushServer.this) {
+ mRunning = false;
+ if (mServerSocket != null) {
+ try {
+ mServerSocket.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ mServerSocket = null;
}
- mServerSocket = null;
}
}
}
diff --git a/src/com/android/nfc/nxp/NativeLlcpConnectionlessSocket.java b/src/com/android/nfc/nxp/NativeLlcpConnectionlessSocket.java
deleted file mode 100755
index c9d3b5d..0000000
--- a/src/com/android/nfc/nxp/NativeLlcpConnectionlessSocket.java
+++ /dev/null
@@ -1,78 +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 com.android.nfc.nxp;
-
-import com.android.nfc.DeviceHost;
-import com.android.nfc.LlcpPacket;
-
-import java.io.IOException;
-
-/**
- * LlcpConnectionlessSocket represents a LLCP Connectionless object to be used
- * in a connectionless communication
- */
-public class NativeLlcpConnectionlessSocket implements DeviceHost.LlcpConnectionlessSocket {
-
- private int mHandle;
- private int mSap;
- private int mLinkMiu;
-
- public NativeLlcpConnectionlessSocket() { }
-
- public native boolean doSendTo(int sap, byte[] data);
-
- public native LlcpPacket doReceiveFrom(int linkMiu);
-
- public native boolean doClose();
-
- @Override
- public int getLinkMiu(){
- return mLinkMiu;
- }
-
- @Override
- public int getSap(){
- return mSap;
- }
-
- @Override
- public void send(int sap, byte[] data) throws IOException {
- if (!doSendTo(sap, data)) {
- throw new IOException();
- }
- }
-
- @Override
- public LlcpPacket receive() throws IOException {
- LlcpPacket packet = doReceiveFrom(mLinkMiu);
- if (packet == null) {
- throw new IOException();
- }
- return packet;
- }
-
- public int getHandle(){
- return mHandle;
- }
-
- @Override
- public void close() throws IOException {
- if (!doClose()) {
- throw new IOException();
- }
- }
-}
diff --git a/src/com/android/nfc/nxp/NativeLlcpServiceSocket.java b/src/com/android/nfc/nxp/NativeLlcpServiceSocket.java
deleted file mode 100755
index 531afd8..0000000
--- a/src/com/android/nfc/nxp/NativeLlcpServiceSocket.java
+++ /dev/null
@@ -1,53 +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 com.android.nfc.nxp;
-
-import com.android.nfc.DeviceHost;
-import com.android.nfc.DeviceHost.LlcpSocket;
-
-import java.io.IOException;
-
-/**
- * LlcpServiceSocket represents a LLCP Service to be used in a
- * Connection-oriented communication
- */
-public class NativeLlcpServiceSocket implements DeviceHost.LlcpServerSocket {
- private int mHandle;
- private int mLocalMiu;
- private int mLocalRw;
- private int mLocalLinearBufferLength;
- private int mSap;
- private String mServiceName;
-
- public NativeLlcpServiceSocket(){ }
-
- private native NativeLlcpSocket doAccept(int miu, int rw, int linearBufferLength);
- @Override
- public LlcpSocket accept() throws IOException {
- LlcpSocket socket = doAccept(mLocalMiu, mLocalRw, mLocalLinearBufferLength);
- if (socket == null) throw new IOException();
- return socket;
- }
-
- private native boolean doClose();
- @Override
- public void close() throws IOException {
- if (!doClose()) {
- throw new IOException();
- }
- }
-}
diff --git a/src/com/android/nfc/nxp/NativeLlcpSocket.java b/src/com/android/nfc/nxp/NativeLlcpSocket.java
deleted file mode 100755
index a337d35..0000000
--- a/src/com/android/nfc/nxp/NativeLlcpSocket.java
+++ /dev/null
@@ -1,99 +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 com.android.nfc.nxp;
-
-import com.android.nfc.DeviceHost;
-
-import java.io.IOException;
-
-/**
- * LlcpClientSocket represents a LLCP Connection-Oriented client to be used in a
- * connection-oriented communication
- */
-public class NativeLlcpSocket implements DeviceHost.LlcpSocket {
- private int mHandle;
- private int mSap;
- private int mLocalMiu;
- private int mLocalRw;
-
- public NativeLlcpSocket(){ }
-
- private native boolean doConnect(int nSap);
- @Override
- public void connectToSap(int sap) throws IOException {
- if (!doConnect(sap)) {
- throw new IOException();
- }
- }
-
- private native boolean doConnectBy(String sn);
- @Override
- public void connectToService(String serviceName) throws IOException {
- if (!doConnectBy(serviceName)) {
- throw new IOException();
- }
- }
-
- private native boolean doClose();
- @Override
- public void close() throws IOException {
- if (!doClose()) {
- throw new IOException();
- }
- }
-
- private native boolean doSend(byte[] data);
- @Override
- public void send(byte[] data) throws IOException {
- if (!doSend(data)) {
- throw new IOException();
- }
- }
-
- private native int doReceive(byte[] recvBuff);
- @Override
- public int receive(byte[] recvBuff) throws IOException {
- int receiveLength = doReceive(recvBuff);
- if (receiveLength == -1) {
- throw new IOException();
- }
- return receiveLength;
- }
-
- private native int doGetRemoteSocketMiu();
- @Override
- public int getRemoteMiu() { return doGetRemoteSocketMiu(); }
-
- private native int doGetRemoteSocketRw();
- @Override
- public int getRemoteRw() { return doGetRemoteSocketRw(); }
-
- @Override
- public int getLocalSap(){
- return mSap;
- }
-
- @Override
- public int getLocalMiu(){
- return mLocalMiu;
- }
-
- @Override
- public int getLocalRw(){
- return mLocalRw;
- }
-}
diff --git a/src/com/android/nfc/nxp/NativeNfcManager.java b/src/com/android/nfc/nxp/NativeNfcManager.java
deleted file mode 100755
index 832da7c..0000000
--- a/src/com/android/nfc/nxp/NativeNfcManager.java
+++ /dev/null
@@ -1,388 +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 com.android.nfc.nxp;
-
-import com.android.nfc.DeviceHost;
-import com.android.nfc.LlcpException;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.nfc.ErrorCodes;
-import android.nfc.tech.Ndef;
-import android.nfc.tech.TagTechnology;
-import android.util.Log;
-
-import java.io.File;
-
-/**
- * Native interface to the NFC Manager functions
- */
-public class NativeNfcManager implements DeviceHost {
- private static final String TAG = "NativeNfcManager";
-
- private static final String NFC_CONTROLLER_FIRMWARE_FILE_NAME = "/vendor/firmware/libpn544_fw.so";
-
- static final String PREF = "NxpDeviceHost";
-
- private static final String PREF_FIRMWARE_MODTIME = "firmware_modtime";
- private static final long FIRMWARE_MODTIME_DEFAULT = -1;
-
- static {
- System.loadLibrary("nfc_jni");
- }
-
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String INTERNAL_TARGET_DESELECTED_ACTION = "com.android.nfc.action.INTERNAL_TARGET_DESELECTED";
-
- /* Native structure */
- private int mNative;
-
- private final DeviceHostListener mListener;
- private final Context mContext;
-
- public NativeNfcManager(Context context, DeviceHostListener listener) {
- mListener = listener;
- initializeNativeStructure();
- mContext = context;
- }
-
- public native boolean initializeNativeStructure();
-
- private native boolean doDownload();
-
- public native int doGetLastError();
-
- @Override
- public void checkFirmware() {
- // Check that the NFC controller firmware is up to date. This
- // ensures that firmware updates are applied in a timely fashion,
- // and makes it much less likely that the user will have to wait
- // for a firmware download when they enable NFC in the settings
- // app. Firmware download can take some time, so this should be
- // run in a separate thread.
-
- // check the timestamp of the firmware file
- File firmwareFile;
- int nbRetry = 0;
- try {
- firmwareFile = new File(NFC_CONTROLLER_FIRMWARE_FILE_NAME);
- } catch(NullPointerException npe) {
- Log.e(TAG,"path to firmware file was null");
- return;
- }
-
- long modtime = firmwareFile.lastModified();
-
- SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
- long prev_fw_modtime = prefs.getLong(PREF_FIRMWARE_MODTIME, FIRMWARE_MODTIME_DEFAULT);
- Log.d(TAG,"prev modtime: " + prev_fw_modtime);
- Log.d(TAG,"new modtime: " + modtime);
- if (prev_fw_modtime == modtime) {
- return;
- }
-
- // FW download.
- while(nbRetry < 5) {
- Log.d(TAG,"Perform Download");
- if(doDownload()) {
- Log.d(TAG,"Download Success");
- // Now that we've finished updating the firmware, save the new modtime.
- prefs.edit().putLong(PREF_FIRMWARE_MODTIME, modtime).apply();
- break;
- } else {
- Log.d(TAG,"Download Failed");
- nbRetry++;
- }
- }
- }
-
- private native boolean doInitialize();
-
- @Override
- public boolean initialize() {
- SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
-
- if (prefs.getBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false)) {
- try {
- Thread.sleep (12000);
- editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false);
- editor.apply();
- } catch (InterruptedException e) { }
- }
-
- return doInitialize();
- }
-
- private native boolean doDeinitialize();
-
- @Override
- public boolean deinitialize() {
- SharedPreferences prefs = mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
-
- editor.putBoolean(NativeNfcSecureElement.PREF_SE_WIRED, false);
- editor.apply();
-
- return doDeinitialize();
- }
-
- @Override
- public native void enableDiscovery();
-
- @Override
- public native void disableDiscovery();
-
- @Override
- public native void enableCE_A();
-
- @Override
- public native void disableCE_A();
-
- @Override
- public native void enableCE_B();
-
- @Override
- public native void disableCE_B();
-
-
- @Override
- public native int[] doGetSecureElementList();
-
- @Override
- public native void doSelectSecureElement();
-
- @Override
- public native void doDeselectSecureElement();
-
-
- private native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap,
- String sn);
-
- @Override
- public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int nSap, String sn)
- throws LlcpException {
- LlcpConnectionlessSocket socket = doCreateLlcpConnectionlessSocket(nSap, sn);
- if (socket != null) {
- return socket;
- } else {
- /* Get Error Status */
- int error = doGetLastError();
-
- Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
-
- switch (error) {
- case ErrorCodes.ERROR_BUFFER_TO_SMALL:
- case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
- throw new LlcpException(error);
- default:
- throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
- }
- }
- }
-
- private native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu,
- int rw, int linearBufferLength);
- @Override
- public LlcpServerSocket createLlcpServerSocket(int nSap, String sn, int miu,
- int rw, int linearBufferLength) throws LlcpException {
- LlcpServerSocket socket = doCreateLlcpServiceSocket(nSap, sn, miu, rw, linearBufferLength);
- if (socket != null) {
- return socket;
- } else {
- /* Get Error Status */
- int error = doGetLastError();
-
- Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
-
- switch (error) {
- case ErrorCodes.ERROR_BUFFER_TO_SMALL:
- case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
- throw new LlcpException(error);
- default:
- throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
- }
- }
- }
-
- private native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw,
- int linearBufferLength);
- @Override
- public LlcpSocket createLlcpSocket(int sap, int miu, int rw,
- int linearBufferLength) throws LlcpException {
- LlcpSocket socket = doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
- if (socket != null) {
- return socket;
- } else {
- /* Get Error Status */
- int error = doGetLastError();
-
- Log.d(TAG, "failed to create llcp socket: " + ErrorCodes.asString(error));
-
- switch (error) {
- case ErrorCodes.ERROR_BUFFER_TO_SMALL:
- case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
- throw new LlcpException(error);
- default:
- throw new LlcpException(ErrorCodes.ERROR_SOCKET_CREATION);
- }
- }
- }
-
- @Override
- public native boolean doCheckLlcp();
-
- @Override
- public native boolean doActivateLlcp();
-
- private native void doResetTimeouts();
-
- @Override
- public void resetTimeouts() {
- doResetTimeouts();
- }
-
- @Override
- public native void doAbort();
-
- private native boolean doSetTimeout(int tech, int timeout);
- @Override
- public boolean setTimeout(int tech, int timeout) {
- return doSetTimeout(tech, timeout);
- }
-
- private native int doGetTimeout(int tech);
- @Override
- public int getTimeout(int tech) {
- return doGetTimeout(tech);
- }
-
-
- @Override
- public boolean canMakeReadOnly(int ndefType) {
- return (ndefType == Ndef.TYPE_1 || ndefType == Ndef.TYPE_2 ||
- ndefType == Ndef.TYPE_MIFARE_CLASSIC);
- }
-
- @Override
- public int getMaxTransceiveLength(int technology) {
- switch (technology) {
- case (TagTechnology.NFC_A):
- case (TagTechnology.MIFARE_CLASSIC):
- case (TagTechnology.MIFARE_ULTRALIGHT):
- return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
- case (TagTechnology.NFC_B):
- return 0; // PN544 does not support transceive of raw NfcB
- case (TagTechnology.NFC_V):
- return 253; // PN544 RF buffer = 255 bytes, subtract two for CRC
- case (TagTechnology.ISO_PCD_A):
- case (TagTechnology.ISO_PCD_B):
- case (TagTechnology.ISO_DEP):
- /* The maximum length of a normal IsoDep frame consists of:
- * CLA, INS, P1, P2, LC, LE + 255 payload bytes = 261 bytes
- * such a frame is supported. Extended length frames however
- * are not supported.
- */
- return 261; // Will be automatically split in two frames on the RF layer
- case (TagTechnology.NFC_F):
- return 252; // PN544 RF buffer = 255 bytes, subtract one for SoD, two for CRC
- default:
- return 0;
- }
-
- }
-
- private native void doSetP2pInitiatorModes(int modes);
- @Override
- public void setP2pInitiatorModes(int modes) {
- doSetP2pInitiatorModes(modes);
- }
-
- private native void doSetP2pTargetModes(int modes);
- @Override
- public void setP2pTargetModes(int modes) {
- doSetP2pTargetModes(modes);
- }
-
- public boolean getExtendedLengthApdusSupported() {
- // Not supported on the PN544
- return false;
- }
-
- private native String doDump();
- @Override
- public String dump() {
- return doDump();
- }
-
- /**
- * Notifies Ndef Message (TODO: rename into notifyTargetDiscovered)
- */
- private void notifyNdefMessageListeners(NativeNfcTag tag) {
- mListener.onRemoteEndpointDiscovered(tag);
- }
-
- /**
- * Notifies transaction
- */
- private void notifyTargetDeselected() {
- mListener.onCardEmulationDeselected();
- }
-
- /**
- * Notifies transaction
- */
- private void notifyTransactionListeners(byte[] aid) {
- mListener.onCardEmulationAidSelected(aid);
- }
-
- /**
- * Notifies P2P Device detected, to activate LLCP link
- */
- private void notifyLlcpLinkActivation(NativeP2pDevice device) {
- mListener.onLlcpLinkActivated(device);
- }
-
- /**
- * Notifies P2P Device detected, to activate LLCP link
- */
- private void notifyLlcpLinkDeactivated(NativeP2pDevice device) {
- mListener.onLlcpLinkDeactivated(device);
- }
-
- private void notifySeFieldActivated() {
- mListener.onRemoteFieldActivated();
- }
-
- private void notifySeFieldDeactivated() {
- mListener.onRemoteFieldDeactivated();
- }
-
- private void notifySeApduReceived(byte[] apdu) {
- mListener.onSeApduReceived(apdu);
- }
-
- private void notifySeEmvCardRemoval() {
- mListener.onSeEmvCardRemoval();
- }
-
- private void notifySeMifareAccess(byte[] block) {
- mListener.onSeMifareAccess(block);
- }
-}
diff --git a/src/com/android/nfc/nxp/NativeNfcSecureElement.java b/src/com/android/nfc/nxp/NativeNfcSecureElement.java
deleted file mode 100755
index 88f9b9d..0000000
--- a/src/com/android/nfc/nxp/NativeNfcSecureElement.java
+++ /dev/null
@@ -1,67 +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 com.android.nfc.nxp;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-
-
-/**
- * Native interface to the NFC Secure Element functions
- *
- * {@hide}
- */
-public class NativeNfcSecureElement {
-
- static final String PREF_SE_WIRED = "se_wired";
-
- private final Context mContext;
-
- SharedPreferences mPrefs;
- SharedPreferences.Editor mPrefsEditor;
-
- public NativeNfcSecureElement(Context context) {
- mContext = context;
-
- mPrefs = mContext.getSharedPreferences(NativeNfcManager.PREF, Context.MODE_PRIVATE);
- mPrefsEditor = mPrefs.edit();
- }
-
- private native int doNativeOpenSecureElementConnection();
-
- public int doOpenSecureElementConnection() {
- mPrefsEditor.putBoolean(PREF_SE_WIRED, true);
- mPrefsEditor.apply();
-
- return doNativeOpenSecureElementConnection();
- }
-
- private native boolean doNativeDisconnectSecureElementConnection(int handle);
-
- public boolean doDisconnect(int handle) {
- mPrefsEditor.putBoolean(PREF_SE_WIRED, false);
- mPrefsEditor.apply();
-
- return doNativeDisconnectSecureElementConnection(handle);
- }
-
- public native byte[] doTransceive(int handle, byte[] data);
-
- public native int[] doGetTechList(int handle);
-
- public native byte [] doGetUid(int handle);
-}
diff --git a/src/com/android/nfc/nxp/NativeNfcTag.java b/src/com/android/nfc/nxp/NativeNfcTag.java
deleted file mode 100755
index 8996dfb..0000000
--- a/src/com/android/nfc/nxp/NativeNfcTag.java
+++ /dev/null
@@ -1,803 +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 com.android.nfc.nxp;
-
-import com.android.nfc.DeviceHost.TagEndpoint;
-
-import android.nfc.FormatException;
-import android.nfc.NdefMessage;
-import android.nfc.tech.IsoDep;
-import android.nfc.tech.MifareClassic;
-import android.nfc.tech.MifareUltralight;
-import android.nfc.tech.Ndef;
-import android.nfc.tech.NfcA;
-import android.nfc.tech.NfcB;
-import android.nfc.tech.NfcF;
-import android.nfc.tech.NfcV;
-import android.nfc.tech.TagTechnology;
-import android.os.Bundle;
-import android.util.Log;
-
-/**
- * Native interface to the NFC tag functions
- */
-public class NativeNfcTag implements TagEndpoint {
- static final boolean DBG = false;
-
- static final int STATUS_CODE_TARGET_LOST = 146;
-
- private int[] mTechList;
- private int[] mTechHandles;
- private int[] mTechLibNfcTypes;
- private Bundle[] mTechExtras;
- private byte[][] mTechPollBytes;
- private byte[][] mTechActBytes;
- private byte[] mUid;
-
- // mConnectedHandle stores the *real* libnfc handle
- // that we're connected to.
- private int mConnectedHandle;
-
- // mConnectedTechIndex stores to which technology
- // the upper layer stack is connected. Note that
- // we may be connected to a libnfchandle without being
- // connected to a technology - technology changes
- // may occur runtime, whereas the underlying handle
- // could stay present. Usually all technologies are on the
- // same handle, with the exception of multi-protocol
- // tags.
- private int mConnectedTechIndex; // Index in mTechHandles
-
- private final String TAG = "NativeNfcTag";
-
- private boolean mIsPresent; // Whether the tag is known to be still present
-
- private PresenceCheckWatchdog mWatchdog;
- class PresenceCheckWatchdog extends Thread {
-
- private int watchdogTimeout = 125;
-
- private boolean isPresent = true;
- private boolean isStopped = false;
- private boolean isPaused = false;
- private boolean doCheck = true;
-
- public synchronized void pause() {
- isPaused = true;
- doCheck = false;
- this.notifyAll();
- }
-
- public synchronized void doResume() {
- isPaused = false;
- // We don't want to resume presence checking immediately,
- // but go through at least one more wait period.
- doCheck = false;
- this.notifyAll();
- }
-
- public synchronized void end() {
- isStopped = true;
- doCheck = false;
- this.notifyAll();
- }
-
- public synchronized void setTimeout(int timeout) {
- watchdogTimeout = timeout;
- doCheck = false; // Do it only after we have waited "timeout" ms again
- this.notifyAll();
- }
-
- @Override
- public synchronized void run() {
- if (DBG) Log.d(TAG, "Starting background presence check");
- while (isPresent && !isStopped) {
- try {
- if (!isPaused) {
- doCheck = true;
- }
- this.wait(watchdogTimeout);
- if (doCheck) {
- isPresent = doPresenceCheck();
- } else {
- // 1) We are paused, waiting for unpause
- // 2) We just unpaused, do pres check in next iteration
- // (after watchdogTimeout ms sleep)
- // 3) We just set the timeout, wait for this timeout
- // to expire once first.
- // 4) We just stopped, exit loop anyway
- }
- } catch (InterruptedException e) {
- // Activity detected, loop
- }
- }
- mIsPresent = false;
- // Restart the polling loop
-
- Log.d(TAG, "Tag lost, restarting polling loop");
- doDisconnect();
- if (DBG) Log.d(TAG, "Stopping background presence check");
- }
- }
-
- private native int doConnect(int handle);
- public synchronized int connectWithStatus(int technology) {
- if (mWatchdog != null) {
- mWatchdog.pause();
- }
- int status = -1;
- for (int i = 0; i < mTechList.length; i++) {
- if (mTechList[i] == technology) {
- // Get the handle and connect, if not already connected
- if (mConnectedHandle != mTechHandles[i]) {
- // We're not yet connected to this handle, there are
- // a few scenario's here:
- // 1) We are not connected to anything yet - allow
- // 2) We are connected to a technology which has
- // a different handle (multi-protocol tag); we support
- // switching to that.
- if (mConnectedHandle == -1) {
- // Not connected yet
- status = doConnect(mTechHandles[i]);
- } else {
- // Connect to a tech with a different handle
- status = reconnectWithStatus(mTechHandles[i]);
- }
- if (status == 0) {
- mConnectedHandle = mTechHandles[i];
- mConnectedTechIndex = i;
- }
- } else {
- // 1) We are connected to a technology which has the same
- // handle; we do not support connecting at a different
- // level (libnfc auto-activates to the max level on
- // any handle).
- // 2) We are connecting to the ndef technology - always
- // allowed.
- if ((technology == TagTechnology.NDEF) ||
- (technology == TagTechnology.NDEF_FORMATABLE)) {
- status = 0;
- } else {
- if ((technology != TagTechnology.ISO_DEP) &&
- (hasTechOnHandle(TagTechnology.ISO_DEP, mTechHandles[i]))) {
- // Don't allow to connect a -4 tag at a different level
- // than IsoDep, as this is not supported by
- // libNFC.
- status = -1;
- } else {
- status = 0;
- }
- }
- if (status == 0) {
- mConnectedTechIndex = i;
- // Handle was already identical
- }
- }
- break;
- }
- }
- if (mWatchdog != null) {
- mWatchdog.doResume();
- }
- return status;
- }
- @Override
- public synchronized boolean connect(int technology) {
- return connectWithStatus(technology) == 0;
- }
-
- @Override
- public synchronized void startPresenceChecking() {
- // Once we start presence checking, we allow the upper layers
- // to know the tag is in the field.
- mIsPresent = true;
- if (mWatchdog == null) {
- mWatchdog = new PresenceCheckWatchdog();
- mWatchdog.start();
- }
- }
-
- @Override
- public synchronized boolean isPresent() {
- // Returns whether the tag is still in the field to the best
- // of our knowledge.
- return mIsPresent;
- }
- native boolean doDisconnect();
- @Override
- public synchronized boolean disconnect() {
- boolean result = false;
-
- mIsPresent = false;
- if (mWatchdog != null) {
- // Watchdog has already disconnected or will do it
- mWatchdog.end();
- try {
- mWatchdog.join();
- } catch (InterruptedException e) {
- // Should never happen.
- }
- mWatchdog = null;
- result = true;
- } else {
- result = doDisconnect();
- }
-
- mConnectedTechIndex = -1;
- mConnectedHandle = -1;
- return result;
- }
-
- native int doReconnect();
- public synchronized int reconnectWithStatus() {
- if (mWatchdog != null) {
- mWatchdog.pause();
- }
- int status = doReconnect();
- if (mWatchdog != null) {
- mWatchdog.doResume();
- }
- return status;
- }
- @Override
- public synchronized boolean reconnect() {
- return reconnectWithStatus() == 0;
- }
-
- native int doHandleReconnect(int handle);
- public synchronized int reconnectWithStatus(int handle) {
- if (mWatchdog != null) {
- mWatchdog.pause();
- }
- int status = doHandleReconnect(handle);
- if (mWatchdog != null) {
- mWatchdog.doResume();
- }
- return status;
- }
-
- private native byte[] doTransceive(byte[] data, boolean raw, int[] returnCode);
- @Override
- public synchronized byte[] transceive(byte[] data, boolean raw, int[] returnCode) {
- if (mWatchdog != null) {
- mWatchdog.pause();
- }
- byte[] result = doTransceive(data, raw, returnCode);
- if (mWatchdog != null) {
- mWatchdog.doResume();
- }
- return result;
- }
-
- private native int doCheckNdef(int[] ndefinfo);
- private synchronized int checkNdefWithStatus(int[] ndefinfo) {
- if (mWatchdog != null) {
- mWatchdog.pause();
- }
- int status = doCheckNdef(ndefinfo);
- if (mWatchdog != null) {
- mWatchdog.doResume();
- }
- return status;
- }
- @Override
- public synchronized boolean checkNdef(int[] ndefinfo) {
- return checkNdefWithStatus(ndefinfo) == 0;
- }
-
- private native byte[] doRead();
- @Override
- public synchronized byte[] readNdef() {
- if (mWatchdog != null) {
- mWatchdog.pause();
- }
- byte[] result = doRead();
- if (mWatchdog != null) {
- mWatchdog.doResume();
- }
- return result;
- }
-
- private native boolean doWrite(byte[] buf);
- @Override
- public synchronized boolean writeNdef(byte[] buf) {
- if (mWatchdog != null) {
- mWatchdog.pause();
- }
- boolean result = doWrite(buf);
- if (mWatchdog != null) {
- mWatchdog.doResume();
- }
- return result;
- }
-
- native boolean doPresenceCheck();
- @Override
- public synchronized boolean presenceCheck() {
- if (mWatchdog != null) {
- mWatchdog.pause();
- }
- boolean result = doPresenceCheck();
- if (mWatchdog != null) {
- mWatchdog.doResume();
- }
- return result;
- }
-
- native boolean doNdefFormat(byte[] key);
- @Override
- public synchronized boolean formatNdef(byte[] key) {
- if (mWatchdog != null) {
- mWatchdog.pause();
- }
- boolean result = doNdefFormat(key);
- if (mWatchdog != null) {
- mWatchdog.doResume();
- }
- return result;
- }
-
- native boolean doMakeReadonly(byte[] key);
- @Override
- public synchronized boolean makeReadOnly() {
- if (mWatchdog != null) {
- mWatchdog.pause();
- }
- boolean result;
- if (hasTech(TagTechnology.MIFARE_CLASSIC)) {
- result = doMakeReadonly(MifareClassic.KEY_DEFAULT);
- } else {
- // No key needed for other technologies
- result = doMakeReadonly(new byte[] {});
- }
- if (mWatchdog != null) {
- mWatchdog.doResume();
- }
- return result;
- }
-
- native boolean doIsIsoDepNdefFormatable(byte[] poll, byte[] act);
- @Override
- public synchronized boolean isNdefFormatable() {
- if (hasTech(TagTechnology.MIFARE_CLASSIC) || hasTech(TagTechnology.MIFARE_ULTRALIGHT)) {
- // These are always formatable
- return true;
- }
- if (hasTech(TagTechnology.NFC_V)) {
- // Currently libnfc only formats NXP NFC-V tags
- if (mUid[5] >= 1 && mUid[5] <= 3 && mUid[6] == 0x04) {
- return true;
- } else {
- return false;
- }
- }
- // For ISO-DEP, call native code to determine at lower level if format
- // is possible. It will need NFC-A poll/activation time bytes for this.
- if (hasTech(TagTechnology.ISO_DEP)) {
- int nfcaTechIndex = getTechIndex(TagTechnology.NFC_A);
- if (nfcaTechIndex != -1) {
- return doIsIsoDepNdefFormatable(mTechPollBytes[nfcaTechIndex],
- mTechActBytes[nfcaTechIndex]);
- } else {
- return false;
- }
- } else {
- // Formatting not supported by libNFC
- return false;
- }
- }
-
- @Override
- public int getHandle() {
- // This is just a handle for the clients; it can simply use the first
- // technology handle we have.
- if (mTechHandles.length > 0) {
- return mTechHandles[0];
- } else {
- return 0;
- }
- }
-
- @Override
- public byte[] getUid() {
- return mUid;
- }
-
- @Override
- public int[] getTechList() {
- return mTechList;
- }
-
- private int getConnectedHandle() {
- return mConnectedHandle;
- }
-
- private int getConnectedLibNfcType() {
- if (mConnectedTechIndex != -1 && mConnectedTechIndex < mTechLibNfcTypes.length) {
- return mTechLibNfcTypes[mConnectedTechIndex];
- } else {
- return 0;
- }
- }
-
- @Override
- public int getConnectedTechnology() {
- if (mConnectedTechIndex != -1 && mConnectedTechIndex < mTechList.length) {
- return mTechList[mConnectedTechIndex];
- } else {
- return 0;
- }
- }
- native int doGetNdefType(int libnfctype, int javatype);
- private int getNdefType(int libnfctype, int javatype) {
- return doGetNdefType(libnfctype, javatype);
- }
-
- private void addTechnology(int tech, int handle, int libnfctype) {
- int[] mNewTechList = new int[mTechList.length + 1];
- System.arraycopy(mTechList, 0, mNewTechList, 0, mTechList.length);
- mNewTechList[mTechList.length] = tech;
- mTechList = mNewTechList;
-
- int[] mNewHandleList = new int[mTechHandles.length + 1];
- System.arraycopy(mTechHandles, 0, mNewHandleList, 0, mTechHandles.length);
- mNewHandleList[mTechHandles.length] = handle;
- mTechHandles = mNewHandleList;
-
- int[] mNewTypeList = new int[mTechLibNfcTypes.length + 1];
- System.arraycopy(mTechLibNfcTypes, 0, mNewTypeList, 0, mTechLibNfcTypes.length);
- mNewTypeList[mTechLibNfcTypes.length] = libnfctype;
- mTechLibNfcTypes = mNewTypeList;
- }
-
- @Override
- public void removeTechnology(int tech) {
- synchronized (this) {
- int techIndex = getTechIndex(tech);
- if (techIndex != -1) {
- int[] mNewTechList = new int[mTechList.length - 1];
- System.arraycopy(mTechList, 0, mNewTechList, 0, techIndex);
- System.arraycopy(mTechList, techIndex + 1, mNewTechList, techIndex,
- mTechList.length - techIndex - 1);
- mTechList = mNewTechList;
-
- int[] mNewHandleList = new int[mTechHandles.length - 1];
- System.arraycopy(mTechHandles, 0, mNewHandleList, 0, techIndex);
- System.arraycopy(mTechHandles, techIndex + 1, mNewTechList, techIndex,
- mTechHandles.length - techIndex - 1);
- mTechHandles = mNewHandleList;
-
- int[] mNewTypeList = new int[mTechLibNfcTypes.length - 1];
- System.arraycopy(mTechLibNfcTypes, 0, mNewTypeList, 0, techIndex);
- System.arraycopy(mTechLibNfcTypes, techIndex + 1, mNewTypeList, techIndex,
- mTechLibNfcTypes.length - techIndex - 1);
- mTechLibNfcTypes = mNewTypeList;
- }
- }
- }
-
- public void addNdefFormatableTechnology(int handle, int libnfcType) {
- synchronized (this) {
- addTechnology(TagTechnology.NDEF_FORMATABLE, handle, libnfcType);
- }
- }
-
- // This method exists to "patch in" the ndef technologies,
- // which is done inside Java instead of the native JNI code.
- // To not create some nasty dependencies on the order on which things
- // are called (most notably getTechExtras()), it needs some additional
- // checking.
- public void addNdefTechnology(NdefMessage msg, int handle, int libnfcType,
- int javaType, int maxLength, int cardState) {
- synchronized (this) {
- addTechnology(TagTechnology.NDEF, handle, libnfcType);
-
- Bundle extras = new Bundle();
- extras.putParcelable(Ndef.EXTRA_NDEF_MSG, msg);
- extras.putInt(Ndef.EXTRA_NDEF_MAXLENGTH, maxLength);
- extras.putInt(Ndef.EXTRA_NDEF_CARDSTATE, cardState);
- extras.putInt(Ndef.EXTRA_NDEF_TYPE, getNdefType(libnfcType, javaType));
-
- if (mTechExtras == null) {
- // This will build the tech extra's for the first time,
- // including a NULL ref for the NDEF tech we generated above.
- Bundle[] builtTechExtras = getTechExtras();
- builtTechExtras[builtTechExtras.length - 1] = extras;
- }
- else {
- // Tech extras were built before, patch the NDEF one in
- Bundle[] oldTechExtras = getTechExtras();
- Bundle[] newTechExtras = new Bundle[oldTechExtras.length + 1];
- System.arraycopy(oldTechExtras, 0, newTechExtras, 0, oldTechExtras.length);
- newTechExtras[oldTechExtras.length] = extras;
- mTechExtras = newTechExtras;
- }
-
-
- }
- }
-
- private int getTechIndex(int tech) {
- int techIndex = -1;
- for (int i = 0; i < mTechList.length; i++) {
- if (mTechList[i] == tech) {
- techIndex = i;
- break;
- }
- }
- return techIndex;
- }
-
- private boolean hasTech(int tech) {
- boolean hasTech = false;
- for (int i = 0; i < mTechList.length; i++) {
- if (mTechList[i] == tech) {
- hasTech = true;
- break;
- }
- }
- return hasTech;
- }
-
- private boolean hasTechOnHandle(int tech, int handle) {
- boolean hasTech = false;
- for (int i = 0; i < mTechList.length; i++) {
- if (mTechList[i] == tech && mTechHandles[i] == handle) {
- hasTech = true;
- break;
- }
- }
- return hasTech;
-
- }
-
- private boolean isUltralightC() {
- /* Make a best-effort attempt at classifying ULTRALIGHT
- * vs ULTRALIGHT-C (based on NXP's public AN1303).
- * The memory layout is as follows:
- * Page # BYTE1 BYTE2 BYTE3 BYTE4
- * 2 INT1 INT2 LOCK LOCK
- * 3 OTP OTP OTP OTP (NDEF CC if NDEF-formatted)
- * 4 DATA DATA DATA DATA (version info if factory-state)
- *
- * Read four blocks from page 2, which will get us both
- * the lock page, the OTP page and the version info.
- */
- boolean isUltralightC = false;
- byte[] readCmd = { 0x30, 0x02 };
- int[] retCode = new int[2];
- byte[] respData = transceive(readCmd, false, retCode);
- if (respData != null && respData.length == 16) {
- // Check the lock bits (last 2 bytes in page2)
- // and the OTP bytes (entire page 3)
- if (respData[2] == 0 && respData[3] == 0 && respData[4] == 0 &&
- respData[5] == 0 && respData[6] == 0 && respData[7] == 0) {
- // Very likely to be a blank card, look at version info
- // in page 4.
- if ((respData[8] == (byte)0x02) && respData[9] == (byte)0x00) {
- // This is Ultralight-C
- isUltralightC = true;
- } else {
- // 0xFF 0xFF would indicate Ultralight, but we also use Ultralight
- // as a fallback if it's anything else
- isUltralightC = false;
- }
- } else {
- // See if we can find the NDEF CC in the OTP page and if it's
- // smaller than major version two
- if (respData[4] == (byte)0xE1 && ((respData[5] & 0xff) < 0x20)) {
- // OK, got NDEF. Technically we'd have to search for the
- // NDEF TLV as well. However, this would add too much
- // time for discovery and we can make already make a good guess
- // with the data we have here. Byte 2 of the OTP page
- // indicates the size of the tag - 0x06 is UL, anything
- // above indicates UL-C.
- if ((respData[6] & 0xff) > 0x06) {
- isUltralightC = true;
- }
- } else {
- // Fall back to ultralight
- isUltralightC = false;
- }
- }
- }
- return isUltralightC;
- }
-
- @Override
- public Bundle[] getTechExtras() {
- synchronized (this) {
- if (mTechExtras != null) return mTechExtras;
- mTechExtras = new Bundle[mTechList.length];
- for (int i = 0; i < mTechList.length; i++) {
- Bundle extras = new Bundle();
- switch (mTechList[i]) {
- case TagTechnology.NFC_A: {
- byte[] actBytes = mTechActBytes[i];
- if ((actBytes != null) && (actBytes.length > 0)) {
- extras.putShort(NfcA.EXTRA_SAK, (short) (actBytes[0] & (short) 0xFF));
- } else {
- // Unfortunately Jewel doesn't have act bytes,
- // ignore this case.
- }
- extras.putByteArray(NfcA.EXTRA_ATQA, mTechPollBytes[i]);
- break;
- }
-
- case TagTechnology.NFC_B: {
- // What's returned from the PN544 is actually:
- // 4 bytes app data
- // 3 bytes prot info
- byte[] appData = new byte[4];
- byte[] protInfo = new byte[3];
- if (mTechPollBytes[i].length >= 7) {
- System.arraycopy(mTechPollBytes[i], 0, appData, 0, 4);
- System.arraycopy(mTechPollBytes[i], 4, protInfo, 0, 3);
-
- extras.putByteArray(NfcB.EXTRA_APPDATA, appData);
- extras.putByteArray(NfcB.EXTRA_PROTINFO, protInfo);
- }
- break;
- }
-
- case TagTechnology.NFC_F: {
- byte[] pmm = new byte[8];
- byte[] sc = new byte[2];
- if (mTechPollBytes[i].length >= 8) {
- // At least pmm is present
- System.arraycopy(mTechPollBytes[i], 0, pmm, 0, 8);
- extras.putByteArray(NfcF.EXTRA_PMM, pmm);
- }
- if (mTechPollBytes[i].length == 10) {
- System.arraycopy(mTechPollBytes[i], 8, sc, 0, 2);
- extras.putByteArray(NfcF.EXTRA_SC, sc);
- }
- break;
- }
-
- case TagTechnology.ISO_DEP: {
- if (hasTech(TagTechnology.NFC_A)) {
- extras.putByteArray(IsoDep.EXTRA_HIST_BYTES, mTechActBytes[i]);
- }
- else {
- extras.putByteArray(IsoDep.EXTRA_HI_LAYER_RESP, mTechActBytes[i]);
- }
- break;
- }
-
- case TagTechnology.NFC_V: {
- // First byte response flags, second byte DSFID
- if (mTechPollBytes[i] != null && mTechPollBytes[i].length >= 2) {
- extras.putByte(NfcV.EXTRA_RESP_FLAGS, mTechPollBytes[i][0]);
- extras.putByte(NfcV.EXTRA_DSFID, mTechPollBytes[i][1]);
- }
- break;
- }
-
- case TagTechnology.MIFARE_ULTRALIGHT: {
- boolean isUlc = isUltralightC();
- extras.putBoolean(MifareUltralight.EXTRA_IS_UL_C, isUlc);
- break;
- }
-
- default: {
- // Leave the entry in the array null
- continue;
- }
- }
- mTechExtras[i] = extras;
- }
- return mTechExtras;
- }
- }
-
- @Override
- public NdefMessage findAndReadNdef() {
- // Try to find NDEF on any of the technologies.
- int[] technologies = getTechList();
- int[] handles = mTechHandles;
- NdefMessage ndefMsg = null;
- boolean foundFormattable = false;
- int formattableHandle = 0;
- int formattableLibNfcType = 0;
- int status;
-
- for (int techIndex = 0; techIndex < technologies.length; techIndex++) {
- // have we seen this handle before?
- for (int i = 0; i < techIndex; i++) {
- if (handles[i] == handles[techIndex]) {
- continue; // don't check duplicate handles
- }
- }
-
- status = connectWithStatus(technologies[techIndex]);
- if (status != 0) {
- Log.d(TAG, "Connect Failed - status = "+ status);
- if (status == STATUS_CODE_TARGET_LOST) {
- break;
- }
- continue; // try next handle
- }
- // Check if this type is NDEF formatable
- if (!foundFormattable) {
- if (isNdefFormatable()) {
- foundFormattable = true;
- formattableHandle = getConnectedHandle();
- formattableLibNfcType = getConnectedLibNfcType();
- // We'll only add formattable tech if no ndef is
- // found - this is because libNFC refuses to format
- // an already NDEF formatted tag.
- }
- reconnect();
- }
-
- int[] ndefinfo = new int[2];
- status = checkNdefWithStatus(ndefinfo);
- if (status != 0) {
- Log.d(TAG, "Check NDEF Failed - status = " + status);
- if (status == STATUS_CODE_TARGET_LOST) {
- break;
- }
- continue; // try next handle
- }
-
- // found our NDEF handle
- boolean generateEmptyNdef = false;
-
- int supportedNdefLength = ndefinfo[0];
- int cardState = ndefinfo[1];
- byte[] buff = readNdef();
- if (buff != null) {
- try {
- ndefMsg = new NdefMessage(buff);
- addNdefTechnology(ndefMsg,
- getConnectedHandle(),
- getConnectedLibNfcType(),
- getConnectedTechnology(),
- supportedNdefLength, cardState);
- reconnect();
- } catch (FormatException e) {
- // Create an intent anyway, without NDEF messages
- generateEmptyNdef = true;
- }
- } else {
- generateEmptyNdef = true;
- }
-
- if (generateEmptyNdef) {
- ndefMsg = null;
- addNdefTechnology(null,
- getConnectedHandle(),
- getConnectedLibNfcType(),
- getConnectedTechnology(),
- supportedNdefLength, cardState);
- reconnect();
- }
- break;
- }
-
- if (ndefMsg == null && foundFormattable) {
- // Tag is not NDEF yet, and found a formattable target,
- // so add formattable tech to tech list.
- addNdefFormatableTechnology(
- formattableHandle,
- formattableLibNfcType);
- }
-
- return ndefMsg;
- }
-}
diff --git a/src/com/android/nfc/nxp/NativeP2pDevice.java b/src/com/android/nfc/nxp/NativeP2pDevice.java
deleted file mode 100755
index 7c7db41..0000000
--- a/src/com/android/nfc/nxp/NativeP2pDevice.java
+++ /dev/null
@@ -1,77 +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 com.android.nfc.nxp;
-
-import com.android.nfc.DeviceHost.NfcDepEndpoint;
-
-/**
- * Native interface to the P2P Initiator functions
- */
-public class NativeP2pDevice implements NfcDepEndpoint {
-
- private int mHandle;
-
- private int mMode;
-
- private byte[] mGeneralBytes;
-
- private native byte[] doReceive();
- @Override
- public byte[] receive() {
- return doReceive();
- }
-
- private native boolean doSend(byte[] data);
- @Override
- public boolean send(byte[] data) {
- return doSend(data);
- }
-
- private native boolean doConnect();
- @Override
- public boolean connect() {
- return doConnect();
- }
-
- private native boolean doDisconnect();
- @Override
- public boolean disconnect() {
- return doDisconnect();
- }
-
- public native byte[] doTransceive(byte[] data);
- @Override
- public byte[] transceive(byte[] data) {
- return doTransceive(data);
- }
-
- @Override
- public int getHandle() {
- return mHandle;
- }
-
- @Override
- public int getMode() {
- return mMode;
- }
-
- @Override
- public byte[] getGeneralBytes() {
- return mGeneralBytes;
- }
-
-}
diff --git a/src/com/android/nfc/snep/SnepClient.java b/src/com/android/nfc/snep/SnepClient.java
index 8dca6ae..fae8143 100644
--- a/src/com/android/nfc/snep/SnepClient.java
+++ b/src/com/android/nfc/snep/SnepClient.java
@@ -29,7 +29,8 @@ public final class SnepClient {
private static final String TAG = "SnepClient";
private static final boolean DBG = false;
private static final int DEFAULT_ACCEPTABLE_LENGTH = 100*1024;
- private static final int MIU = 128;
+ private static final int DEFAULT_MIU = 128;
+ private static final int DEFAULT_RWSIZE = 1;
SnepMessenger mMessenger = null;
private final Object mTransmissionLock = new Object();
@@ -38,6 +39,8 @@ public final class SnepClient {
private int mState = DISCONNECTED;
private final int mAcceptableLength;
private final int mFragmentLength;
+ private final int mMiu;
+ private final int mRwSize;
private static final int DISCONNECTED = 0;
private static final int CONNECTING = 1;
@@ -48,6 +51,8 @@ public final class SnepClient {
mPort = SnepServer.DEFAULT_PORT;
mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
mFragmentLength = -1;
+ mMiu = DEFAULT_MIU;
+ mRwSize = DEFAULT_RWSIZE;
}
public SnepClient(String serviceName) {
@@ -55,6 +60,17 @@ public final class SnepClient {
mPort = -1;
mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
mFragmentLength = -1;
+ mMiu = DEFAULT_MIU;
+ mRwSize = DEFAULT_RWSIZE;
+ }
+
+ public SnepClient(int miu, int rwSize) {
+ mServiceName = SnepServer.DEFAULT_SERVICE_NAME;
+ mPort = SnepServer.DEFAULT_PORT;
+ mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
+ mFragmentLength = -1;
+ mMiu = miu;
+ mRwSize = rwSize;
}
SnepClient(String serviceName, int fragmentLength) {
@@ -62,6 +78,8 @@ public final class SnepClient {
mPort = -1;
mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
mFragmentLength = fragmentLength;
+ mMiu = DEFAULT_MIU;
+ mRwSize = DEFAULT_RWSIZE;
}
SnepClient(String serviceName, int acceptableLength, int fragmentLength) {
@@ -69,6 +87,8 @@ public final class SnepClient {
mPort = -1;
mAcceptableLength = acceptableLength;
mFragmentLength = fragmentLength;
+ mMiu = DEFAULT_MIU;
+ mRwSize = DEFAULT_RWSIZE;
}
public void put(NdefMessage msg) throws IOException {
@@ -122,7 +142,7 @@ public final class SnepClient {
try {
if (DBG) Log.d(TAG, "about to create socket");
// Connect to the snep server on the remote side
- socket = NfcService.getInstance().createLlcpSocket(0, MIU, 1, 1024);
+ socket = NfcService.getInstance().createLlcpSocket(0, mMiu, mRwSize, 1024);
if (socket == null) {
throw new IOException("Could not connect to socket.");
}
diff --git a/src/com/android/nfc/snep/SnepServer.java b/src/com/android/nfc/snep/SnepServer.java
index 84bb673..aa7da48 100644
--- a/src/com/android/nfc/snep/SnepServer.java
+++ b/src/com/android/nfc/snep/SnepServer.java
@@ -34,9 +34,10 @@ import java.io.IOException;
public final class SnepServer {
private static final String TAG = "SnepServer";
private static final boolean DBG = false;
+ private static final int DEFAULT_MIU = 248;
+ private static final int DEFAULT_RW_SIZE = 1;
public static final int DEFAULT_PORT = 4;
- private static final int MIU = 248;
public static final String DEFAULT_SERVICE_NAME = "urn:nfc:sn:snep";
@@ -44,6 +45,8 @@ public final class SnepServer {
final String mServiceName;
final int mServiceSap;
final int mFragmentLength;
+ final int mMiu;
+ final int mRwSize;
/** Protected by 'this', null when stopped, non-null when running */
ServerThread mServerThread = null;
@@ -59,6 +62,8 @@ public final class SnepServer {
mServiceName = DEFAULT_SERVICE_NAME;
mServiceSap = DEFAULT_PORT;
mFragmentLength = -1;
+ mMiu = DEFAULT_MIU;
+ mRwSize = DEFAULT_RW_SIZE;
}
public SnepServer(String serviceName, int serviceSap, Callback callback) {
@@ -66,6 +71,17 @@ public final class SnepServer {
mServiceName = serviceName;
mServiceSap = serviceSap;
mFragmentLength = -1;
+ mMiu = DEFAULT_MIU;
+ mRwSize = DEFAULT_RW_SIZE;
+ }
+
+ public SnepServer(Callback callback, int miu, int rwSize) {
+ mCallback = callback;
+ mServiceName = DEFAULT_SERVICE_NAME;
+ mServiceSap = DEFAULT_PORT;
+ mFragmentLength = -1;
+ mMiu = miu;
+ mRwSize = rwSize;
}
SnepServer(String serviceName, int serviceSap, int fragmentLength, Callback callback) {
@@ -73,6 +89,8 @@ public final class SnepServer {
mServiceName = serviceName;
mServiceSap = serviceSap;
mFragmentLength = fragmentLength;
+ mMiu = DEFAULT_MIU;
+ mRwSize = DEFAULT_RW_SIZE;
}
/** Connection class, used to handle incoming connections */
@@ -168,7 +186,7 @@ public final class SnepServer {
try {
synchronized (SnepServer.this) {
mServerSocket = NfcService.getInstance().createLlcpServerSocket(mServiceSap,
- mServiceName, MIU, 1, 1024);
+ mServiceName, mMiu, mRwSize, 1024);
}
if (mServerSocket == null) {
if (DBG) Log.d(TAG, "failed to create LLCP service socket");