Merge changes from topics "Deprecate-android-beam", "Dynamic_Default_Aid_Route"
* changes:
Remove NFC LiveCase functionality
Start P2P services only if Android Beam is supported
Add routing mechanism for NFC CE
diff --git a/nci/jni/NativeNfcManager.cpp b/nci/jni/NativeNfcManager.cpp
index 9eebba8..77d31cc 100755
--- a/nci/jni/NativeNfcManager.cpp
+++ b/nci/jni/NativeNfcManager.cpp
@@ -865,10 +865,17 @@
*******************************************************************************/
static jboolean nfcManager_routeAid(JNIEnv* e, jobject, jbyteArray aid,
jint route, jint aidInfo) {
- ScopedByteArrayRO bytes(e, aid);
- uint8_t* buf =
- const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0]));
- size_t bufLen = bytes.size();
+ uint8_t* buf;
+ size_t bufLen;
+
+ if (aid == NULL) {
+ buf = NULL;
+ bufLen = 0;
+ } else {
+ ScopedByteArrayRO bytes(e, aid);
+ buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0]));
+ bufLen = bytes.size();
+ }
return RoutingManager::getInstance().addAidRouting(buf, bufLen, route,
aidInfo);
}
@@ -885,10 +892,17 @@
**
*******************************************************************************/
static jboolean nfcManager_unrouteAid(JNIEnv* e, jobject, jbyteArray aid) {
- ScopedByteArrayRO bytes(e, aid);
- uint8_t* buf =
- const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0]));
- size_t bufLen = bytes.size();
+ uint8_t* buf;
+ size_t bufLen;
+
+ if (aid == NULL) {
+ buf = NULL;
+ bufLen = 0;
+ } else {
+ ScopedByteArrayRO bytes(e, aid);
+ buf = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(&bytes[0]));
+ bufLen = bytes.size();
+ }
bool result = RoutingManager::getInstance().removeAidRouting(buf, bufLen);
return result;
}
@@ -1731,9 +1745,9 @@
if (state == NFA_SCREEN_STATE_OFF_LOCKED ||
state == NFA_SCREEN_STATE_OFF_UNLOCKED) {
- // disable both poll and listen on DH 0x02
+ // disable poll and enable listen on DH 0x00
discovry_param =
- NCI_POLLING_DH_DISABLE_MASK | NCI_LISTEN_DH_NFCEE_DISABLE_MASK;
+ NCI_POLLING_DH_DISABLE_MASK | NCI_LISTEN_DH_NFCEE_ENABLE_MASK;
}
if (state == NFA_SCREEN_STATE_ON_LOCKED) {
@@ -1867,6 +1881,19 @@
return NfcConfig::getUnsigned(NAME_ISO_DEP_MAX_TRANSCEIVE, 261);
}
+/*******************************************************************************
+ **
+ ** Function: nfcManager_getAidTableSize
+ ** Description: Get the maximum supported size for AID routing table.
+ **
+ ** e: JVM environment.
+ ** o: Java object.
+ **
+ *******************************************************************************/
+static jint nfcManager_getAidTableSize(JNIEnv*, jobject) {
+ return NFA_GetAidTableSize();
+}
+
/*****************************************************************************
**
** JNI functions for android-4.0.1_r1
@@ -1949,7 +1976,9 @@
{"doShutdown", "()V", (void*)nfcManager_doShutdown},
{"getIsoDepMaxTransceiveLength", "()I",
- (void*)nfcManager_getIsoDepMaxTransceiveLength}
+ (void*)nfcManager_getIsoDepMaxTransceiveLength},
+
+ {"getAidTableSize", "()I", (void*)nfcManager_getAidTableSize},
};
diff --git a/nci/jni/RoutingManager.cpp b/nci/jni/RoutingManager.cpp
index f4cfd04..b780c9e 100755
--- a/nci/jni/RoutingManager.cpp
+++ b/nci/jni/RoutingManager.cpp
@@ -49,14 +49,18 @@
(void*)RoutingManager::
com_android_nfc_cardemulation_doGetOffHostEseDestination},
{"doGetAidMatchingMode", "()I",
- (void*)
- RoutingManager::com_android_nfc_cardemulation_doGetAidMatchingMode}};
+ (void*)RoutingManager::com_android_nfc_cardemulation_doGetAidMatchingMode},
+ {"doGetDefaultIsoDepRouteDestination", "()I",
+ (void*)RoutingManager::
+ com_android_nfc_cardemulation_doGetDefaultIsoDepRouteDestination}};
static const int MAX_NUM_EE = 5;
// SCBR from host works only when App is in foreground
static const uint8_t SYS_CODE_PWR_STATE_HOST = 0x01;
static const uint16_t DEFAULT_SYS_CODE = 0xFEFE;
+static const uint8_t AID_ROUTE_QUAL_PREFIX = 0x10;
+
RoutingManager::RoutingManager() : mAidRoutingConfigured(false) {
static const char fn[] = "RoutingManager::RoutingManager()";
@@ -101,6 +105,8 @@
mOffHostAidRoutingPowerState =
NfcConfig::getUnsigned(NAME_OFFHOST_AID_ROUTE_PWR_STATE, 0x01);
+ mDefaultIsoDepRoute = NfcConfig::getUnsigned(NAME_DEFAULT_ISODEP_ROUTE, 0x0);
+
memset(&mEeInfo, 0, sizeof(mEeInfo));
mReceivedEeInfo = false;
mSeTechMask = 0x00;
@@ -129,6 +135,7 @@
}
mRxDataBuffer.clear();
+ mSeTechMask = 0x00;
if ((mDefaultOffHostRoute != 0) || (mDefaultFelicaRoute != 0)) {
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf(
@@ -222,6 +229,21 @@
} else {
LOG(ERROR) << StringPrintf("%s: Fail to register system code", fn);
}
+
+ // Register zero lengthy Aid for default Aid Routing
+ if (mDefaultEe != mDefaultIsoDepRoute) {
+ uint8_t powerState =
+ (mDefaultEe != 0x00) ? mOffHostAidRoutingPowerState : 0x11;
+ nfaStat = NFA_EeAddAidRouting(mDefaultEe, 0, NULL, powerState,
+ AID_ROUTE_QUAL_PREFIX);
+ if (nfaStat == NFA_STATUS_OK) {
+ DLOG_IF(INFO, nfc_debug_enabled)
+ << StringPrintf("%s: Succeed to register zero length AID", fn);
+ } else {
+ LOG(ERROR) << StringPrintf("%s: failed to register zero length AID",
+ fn);
+ }
+ }
}
return true;
}
@@ -251,20 +273,20 @@
LOG(ERROR) << StringPrintf(
"Fail to set default tech routing for Nfc-A/Nfc-F");
}
- // Default routing for IsoDep and T3T protocol
- if (mIsScbrSupported)
- protoMask = NFA_PROTOCOL_MASK_ISO_DEP;
- else
- protoMask = (NFA_PROTOCOL_MASK_ISO_DEP | NFA_PROTOCOL_MASK_T3T);
- nfaStat = NFA_EeSetDefaultProtoRouting(
- mDefaultEe, protoMask, 0, 0, protoMask, mDefaultEe ? protoMask : 0,
- mDefaultEe ? protoMask : 0);
- if (nfaStat == NFA_STATUS_OK)
- mRoutingEvent.wait();
- else
- LOG(ERROR) << StringPrintf(
- "Fail to set default proto routing for protocol: 0x%x", protoMask);
+ // Default routing for T3T protocol
+ if (!mIsScbrSupported) {
+ protoMask = NFA_PROTOCOL_MASK_T3T;
+
+ nfaStat = NFA_EeSetDefaultProtoRouting(
+ mDefaultEe, protoMask, 0, 0, protoMask, mDefaultEe ? protoMask : 0,
+ mDefaultEe ? protoMask : 0);
+ if (nfaStat == NFA_STATUS_OK)
+ mRoutingEvent.wait();
+ else
+ LOG(ERROR) << StringPrintf(
+ "Fail to set default proto routing for protocol: 0x%x", protoMask);
+ }
} else {
// Route Nfc-A to host if we don't have a SE
techMask = NFA_TECHNOLOGY_MASK_A;
@@ -277,16 +299,6 @@
LOG(ERROR) << StringPrintf(
"Fail to set default tech routing for Nfc-A");
}
- // Default routing for IsoDep protocol
- protoMask = NFA_PROTOCOL_MASK_ISO_DEP;
- nfaStat = NFA_EeSetDefaultProtoRouting(
- mDefaultEe, protoMask, 0, 0, protoMask, mDefaultEe ? protoMask : 0,
- mDefaultEe ? protoMask : 0);
- if (nfaStat == NFA_STATUS_OK)
- mRoutingEvent.wait();
- else
- LOG(ERROR) << StringPrintf(
- "Fail to set default proto routing for IsoDep");
// Route Nfc-F to host if we don't have a SE
techMask = NFA_TECHNOLOGY_MASK_F;
@@ -310,6 +322,29 @@
LOG(ERROR) << StringPrintf("Fail to set default proto routing for T3T");
}
}
+ // Default routing for IsoDep protocol
+ protoMask = NFA_PROTOCOL_MASK_ISO_DEP;
+ if ((mSeTechMask & (NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B |
+ NFA_TECHNOLOGY_MASK_F)) == 0) {
+ nfaStat = NFA_EeSetDefaultProtoRouting(NFC_DH_ID, protoMask, 0, 0,
+ protoMask, 0, 0);
+ if (nfaStat == NFA_STATUS_OK)
+ mRoutingEvent.wait();
+ else
+ LOG(ERROR) << StringPrintf(
+ "Fail to set default proto routing for IsoDep");
+
+ } else {
+ nfaStat = NFA_EeSetDefaultProtoRouting(
+ mDefaultIsoDepRoute, protoMask, mDefaultIsoDepRoute ? protoMask : 0, 0,
+ protoMask, mDefaultIsoDepRoute ? protoMask : 0,
+ mDefaultIsoDepRoute ? protoMask : 0);
+ if (nfaStat == NFA_STATUS_OK)
+ mRoutingEvent.wait();
+ else
+ LOG(ERROR) << StringPrintf(
+ "Fail to set default proto routing for IsoDep");
+ }
}
void RoutingManager::disableRoutingToHost() {
@@ -380,7 +415,7 @@
int route, int aidInfo) {
static const char fn[] = "RoutingManager::addAidRouting";
DLOG_IF(INFO, nfc_debug_enabled) << StringPrintf("%s: enter", fn);
- uint8_t powerState = (route != 0x00) ? mOffHostAidRoutingPowerState : 0x01;
+ uint8_t powerState = (route != 0x00) ? mOffHostAidRoutingPowerState : 0x11;
SyncEventGuard guard(mRoutingEvent);
mAidRoutingConfigured = false;
tNFA_STATUS nfaStat =
@@ -936,3 +971,8 @@
JNIEnv*) {
return getInstance().mAidMatchingMode;
}
+
+int RoutingManager::
+ com_android_nfc_cardemulation_doGetDefaultIsoDepRouteDestination(JNIEnv*) {
+ return getInstance().mDefaultIsoDepRoute;
+}
diff --git a/nci/jni/RoutingManager.h b/nci/jni/RoutingManager.h
index 37f59d4..700a22e 100755
--- a/nci/jni/RoutingManager.h
+++ b/nci/jni/RoutingManager.h
@@ -78,6 +78,8 @@
static jbyteArray com_android_nfc_cardemulation_doGetOffHostEseDestination(
JNIEnv* e);
static int com_android_nfc_cardemulation_doGetAidMatchingMode(JNIEnv* e);
+ static int com_android_nfc_cardemulation_doGetDefaultIsoDepRouteDestination(
+ JNIEnv* e);
std::vector<uint8_t> mRxDataBuffer;
map<int, uint16_t> mMapScbrHandle;
@@ -89,6 +91,7 @@
vector<uint8_t> mOffHostRouteEse;
int mDefaultFelicaRoute;
int mDefaultEe;
+ int mDefaultIsoDepRoute;
int mAidMatchingMode;
int mNfcFOnDhHandle;
bool mIsScbrSupported;
diff --git a/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
index 2c493d3..06eda20 100755
--- a/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
+++ b/nci/src/com/android/nfc/dhimpl/NativeNfcManager.java
@@ -331,6 +331,8 @@
}
+ public native int getAidTableSize();
+
private native void doSetP2pInitiatorModes(int modes);
@Override
public void setP2pInitiatorModes(int modes) {
diff --git a/res/values/live_cases.xml b/res/values/live_cases.xml
deleted file mode 100644
index d5c9d48..0000000
--- a/res/values/live_cases.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2013 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.
--->
-
-<!-- NFC resources that may need to be customized
- for different hardware or product builds. -->
-<resources>
- <!-- Whether the device can receive NFC data in setup wizard -->
- <bool name="enable_live_cases">true</bool>
-
- <!-- The accepted mime-types when NFC is enabled at locked screen.
- Mime-types must be lower case, wildcards are *not* accepted. -->
- <string-array name="live_case_mime_types" translatable="false">
- <item>application/vnd.google.android.apps.workshop</item>
- <item>application/vnd.google.android.apps.live_case</item>
- </string-array>
-
- <!-- The accepted tag technology types which will be detected for live case
- NFC at lock screen. Mime-types must be lower case, wildcards are *not*
- accepted. -->
- <string-array name="live_case_tag_types" translatable="false">
- <item>TypeA</item>
- </string-array>
-</resources>
diff --git a/src/com/android/nfc/DeviceHost.java b/src/com/android/nfc/DeviceHost.java
index 5469fbf..94ddf91 100644
--- a/src/com/android/nfc/DeviceHost.java
+++ b/src/com/android/nfc/DeviceHost.java
@@ -225,6 +225,8 @@
int getMaxTransceiveLength(int technology);
+ public int getAidTableSize();
+
void setP2pInitiatorModes(int modes);
void setP2pTargetModes(int modes);
diff --git a/src/com/android/nfc/NfcDispatcher.java b/src/com/android/nfc/NfcDispatcher.java
index 9003636..02569c1 100644
--- a/src/com/android/nfc/NfcDispatcher.java
+++ b/src/com/android/nfc/NfcDispatcher.java
@@ -87,7 +87,6 @@
private final ContentResolver mContentResolver;
private final HandoverDataParser mHandoverDataParser;
private final String[] mProvisioningMimes;
- private final String[] mLiveCaseMimes;
private final ScreenStateHelper mScreenStateHelper;
private final NfcUnlockManager mNfcUnlockManager;
private final boolean mDeviceSupportsBluetooth;
@@ -103,8 +102,7 @@
NfcDispatcher(Context context,
HandoverDataParser handoverDataParser,
- boolean provisionOnly,
- boolean isLiveCaseEnabled) {
+ boolean provisionOnly) {
mContext = context;
mIActivityManager = ActivityManager.getService();
mTechListFilters = new RegisteredComponentCache(mContext,
@@ -130,18 +128,6 @@
}
mProvisioningMimes = provisionMimes;
- String[] liveCaseMimes = null;
- if (isLiveCaseEnabled) {
- try {
- // Get accepted mime-types
- liveCaseMimes = context.getResources().
- getStringArray(R.array.live_case_mime_types);
- } catch (NotFoundException e) {
- liveCaseMimes = null;
- }
- }
- mLiveCaseMimes = liveCaseMimes;
-
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
mContext.registerReceiver(mBluetoothStatusReceiver, filter);
}
@@ -283,9 +269,9 @@
IntentFilter[] overrideFilters;
String[][] overrideTechLists;
String[] provisioningMimes;
- String[] liveCaseMimes;
- NdefMessage message = null;
boolean provisioningOnly;
+ NdefMessage message = null;
+ Ndef ndef = Ndef.get(tag);
synchronized (this) {
overrideFilters = mOverrideFilters;
@@ -293,28 +279,13 @@
overrideTechLists = mOverrideTechLists;
provisioningOnly = mProvisioningOnly;
provisioningMimes = mProvisioningMimes;
- liveCaseMimes = mLiveCaseMimes;
}
boolean screenUnlocked = false;
- boolean liveCaseDetected = false;
- Ndef ndef = Ndef.get(tag);
if (!provisioningOnly &&
mScreenStateHelper.checkScreenState() == ScreenStateHelper.SCREEN_STATE_ON_LOCKED) {
screenUnlocked = handleNfcUnlock(tag);
-
- if (ndef != null) {
- message = ndef.getCachedNdefMessage();
- if (message != null) {
- String ndefMimeType = message.getRecords()[0].toMimeType();
- if (liveCaseMimes != null &&
- Arrays.asList(liveCaseMimes).contains(ndefMimeType)) {
- liveCaseDetected = true;
- }
- }
- }
-
- if (!screenUnlocked && !liveCaseDetected)
+ if (!screenUnlocked)
return DISPATCH_FAIL;
}
diff --git a/src/com/android/nfc/NfcService.java b/src/com/android/nfc/NfcService.java
index 8649f10..d5a9595 100644
--- a/src/com/android/nfc/NfcService.java
+++ b/src/com/android/nfc/NfcService.java
@@ -120,7 +120,7 @@
static final String PREF_NFC_ON = "nfc_on";
static final boolean NFC_ON_DEFAULT = true;
static final String PREF_NDEF_PUSH_ON = "ndef_push_on";
- static final boolean NDEF_PUSH_ON_DEFAULT = true;
+ static final boolean NDEF_PUSH_ON_DEFAULT = false;
static final String PREF_FIRST_BEAM = "first_beam";
static final String PREF_FIRST_BOOT = "first_boot";
@@ -273,6 +273,7 @@
boolean mIsDebugBuild;
boolean mIsHceCapable;
boolean mIsHceFCapable;
+ boolean mIsBeamCapable;
private NfcDispatcher mNfcDispatcher;
private PowerManager mPowerManager;
@@ -290,9 +291,6 @@
private static NfcService sService;
public static boolean sIsDtaMode = false;
- boolean mIsLiveCaseEnabled; // whether live cases are enabled
- int mLiveCaseTechnology; // Technology mask of accepted NFC tags
-
private IVrManager vrManager;
boolean mIsVrModeEnabled;
@@ -336,6 +334,7 @@
*/
@Override
public void onLlcpLinkActivated(NfcDepEndpoint device) {
+ if (!mIsBeamCapable) return;
sendMessage(NfcService.MSG_LLCP_LINK_ACTIVATION, device);
}
@@ -344,6 +343,7 @@
*/
@Override
public void onLlcpLinkDeactivated(NfcDepEndpoint device) {
+ if (!mIsBeamCapable) return;
sendMessage(NfcService.MSG_LLCP_LINK_DEACTIVATED, device);
}
@@ -352,6 +352,7 @@
*/
@Override
public void onLlcpFirstPacketReceived(NfcDepEndpoint device) {
+ if (!mIsBeamCapable) return;
mNumP2pDetected.incrementAndGet();
sendMessage(NfcService.MSG_LLCP_LINK_FIRST_PACKET, device);
}
@@ -402,31 +403,6 @@
} catch (NotFoundException e) {
}
- try {
- mIsLiveCaseEnabled = mContext.getResources().getBoolean(R.bool.enable_live_cases);
- } catch (NotFoundException e) {
- mIsLiveCaseEnabled = false;
- }
-
- mLiveCaseTechnology = 0;
- String[] liveCaseTechList;
- try {
- liveCaseTechList = mContext.getResources().getStringArray(R.array.live_case_tag_types);
- for (int i=0; i < liveCaseTechList.length; i++) {
- if (liveCaseTechList[i].equals("TypeA")) {
- mLiveCaseTechnology |= NFC_POLL_A;
- } else if (liveCaseTechList[i].equals("TypeB")) {
- mLiveCaseTechnology |= NFC_POLL_B;
- } else if (liveCaseTechList[i].equals("TypeF")) {
- mLiveCaseTechnology |= NFC_POLL_F;
- } else if (liveCaseTechList[i].equals("TypeV")) {
- mLiveCaseTechnology |= NFC_POLL_V;
- }
- }
- } catch (NotFoundException e) {
- mLiveCaseTechnology = 0;
- }
-
if (isNfcProvisioningEnabled) {
mInProvisionMode = Settings.Global.getInt(mContentResolver,
Settings.Global.DEVICE_PROVISIONED, 0) == 0;
@@ -434,17 +410,12 @@
mInProvisionMode = false;
}
- mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode,
- mIsLiveCaseEnabled);
- mP2pLinkManager = new P2pLinkManager(mContext, mHandoverDataParser,
- mDeviceHost.getDefaultLlcpMiu(), mDeviceHost.getDefaultLlcpRwSize());
+ mNfcDispatcher = new NfcDispatcher(mContext, mHandoverDataParser, mInProvisionMode);
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);
- enforceBeamShareActivityPolicy(mContext, new UserHandle(mUserId));
mIsDebugBuild = "userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE);
@@ -490,6 +461,18 @@
updatePackageCache();
PackageManager pm = mContext.getPackageManager();
+ mIsBeamCapable = pm.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM);
+ mIsNdefPushEnabled =
+ mPrefs.getBoolean(PREF_NDEF_PUSH_ON, NDEF_PUSH_ON_DEFAULT) &&
+ mIsBeamCapable;
+
+ if (mIsBeamCapable) {
+ mP2pLinkManager = new P2pLinkManager(
+ mContext, mHandoverDataParser, mDeviceHost.getDefaultLlcpMiu(),
+ mDeviceHost.getDefaultLlcpRwSize());
+ }
+ enforceBeamShareActivityPolicy(mContext, new UserHandle(mUserId));
+
mIsHceCapable =
pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION) ||
pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
@@ -682,7 +665,9 @@
synchronized (NfcService.this) {
mObjectMap.clear();
- mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
+ if (mIsBeamCapable) {
+ mP2pLinkManager.enableDisable(mIsNdefPushEnabled, true);
+ }
updateState(NfcAdapter.STATE_ON);
}
@@ -725,7 +710,9 @@
mCardEmulationManager.onNfcDisabled();
}
- mP2pLinkManager.enableDisable(false, false);
+ if (mIsBeamCapable) {
+ mP2pLinkManager.enableDisable(false, false);
+ }
// Stop watchdog if tag present
// A convenient way to stop the watchdog properly consists of
@@ -817,8 +804,8 @@
}
}
boolean isActiveForUser =
- (!um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_BEAM, uh)) &&
- isGlobalEnabled;
+ (!um.hasUserRestriction(UserManager.DISALLOW_OUTGOING_BEAM, uh)) &&
+ isGlobalEnabled && mIsBeamCapable;
if (DBG) {
Log.d(TAG, "Enforcing a policy change on user: " + uh.toString() +
", isActiveForUser = " + isActiveForUser);
@@ -905,7 +892,7 @@
public boolean enableNdefPush() throws RemoteException {
NfcPermissions.enforceAdminPermissions(mContext);
synchronized (NfcService.this) {
- if (mIsNdefPushEnabled) {
+ if (mIsNdefPushEnabled || !mIsBeamCapable) {
return true;
}
Log.i(TAG, "enabling NDEF Push");
@@ -925,7 +912,7 @@
public boolean disableNdefPush() throws RemoteException {
NfcPermissions.enforceAdminPermissions(mContext);
synchronized (NfcService.this) {
- if (!mIsNdefPushEnabled) {
+ if (!mIsNdefPushEnabled || !mIsBeamCapable) {
return true;
}
Log.i(TAG, "disabling NDEF Push");
@@ -984,8 +971,9 @@
// don't allow Beam for managed profiles, or devices with a device owner or policy owner
UserInfo userInfo = mUserManager.getUserInfo(UserHandle.getCallingUserId());
- if(!mUserManager.hasUserRestriction(
- UserManager.DISALLOW_OUTGOING_BEAM, userInfo.getUserHandle())) {
+ if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_BEAM,
+ userInfo.getUserHandle()) &&
+ mIsBeamCapable) {
mP2pLinkManager.setNdefCallback(callback, Binder.getCallingUid());
} else if (DBG) {
Log.d(TAG, "Disabling default Beam behavior");
@@ -1035,6 +1023,9 @@
@Override
public void invokeBeam() {
+ if (!mIsBeamCapable) {
+ return;
+ }
NfcPermissions.enforceUserPermissions(mContext);
if (mForegroundUtils.isInForeground(Binder.getCallingUid())) {
@@ -1579,7 +1570,7 @@
int rwSize,int testCaseId) throws RemoteException {
NfcPermissions.enforceAdminPermissions(mContext);
- if(serviceName.equals(null))
+ if (serviceName.equals(null) || !mIsBeamCapable)
return false;
mP2pLinkManager.enableExtDtaSnepServer(serviceName, serviceSap, miu, rwSize,testCaseId);
@@ -1587,6 +1578,8 @@
}
public void disableServer() throws RemoteException {
+ if (!mIsBeamCapable)
+ return;
NfcPermissions.enforceAdminPermissions(mContext);
mP2pLinkManager.disableExtDtaSnepServer();
}
@@ -1595,7 +1588,7 @@
int testCaseId) throws RemoteException {
NfcPermissions.enforceAdminPermissions(mContext);
- if(testCaseId == 0)
+ if (testCaseId == 0 || !mIsBeamCapable)
return false;
if (testCaseId>20){
@@ -1610,8 +1603,10 @@
}
public void disableClient() throws RemoteException {
- NfcPermissions.enforceAdminPermissions(mContext);
- mP2pLinkManager.disableDtaSnepClient();
+ if (!mIsBeamCapable)
+ return;
+ NfcPermissions.enforceAdminPermissions(mContext);
+ mP2pLinkManager.disableDtaSnepClient();
}
public boolean registerMessageService(String msgServiceName)
@@ -1765,18 +1760,15 @@
paramsBuilder.setEnableReaderMode(true);
} else {
paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT);
- paramsBuilder.setEnableP2p(true);
+ paramsBuilder.setEnableP2p(mIsBeamCapable);
}
} else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED && mInProvisionMode) {
paramsBuilder.setTechMask(NfcDiscoveryParameters.NFC_POLL_DEFAULT);
// enable P2P for MFM/EDU/Corp provisioning
- paramsBuilder.setEnableP2p(true);
+ paramsBuilder.setEnableP2p(mIsBeamCapable);
} else if (screenState == ScreenStateHelper.SCREEN_STATE_ON_LOCKED &&
- (mIsLiveCaseEnabled || mNfcUnlockManager.isLockscreenPollingEnabled())) {
+ mNfcUnlockManager.isLockscreenPollingEnabled()) {
int techMask = 0;
- // enable polling for Live Case technologies
- if (mIsLiveCaseEnabled)
- techMask |= mLiveCaseTechnology;
if (mNfcUnlockManager.isLockscreenPollingEnabled())
techMask |= mNfcUnlockManager.getLockscreenPollMask();
paramsBuilder.setTechMask(techMask);
@@ -1904,6 +1896,13 @@
return mDeviceHost.createLlcpServerSocket(sap, sn, miu, rw, linearBufferLength);
}
+ public int getAidRoutingTableSize ()
+ {
+ int aidTableSize = 0x00;
+ aidTableSize = mDeviceHost.getAidTableSize();
+ return aidTableSize;
+ }
+
public void sendMockNdefTag(NdefMessage msg) {
sendMessage(MSG_MOCK_NDEF, msg);
}
@@ -2534,25 +2533,29 @@
sendMessage(NfcService.MSG_APPLY_SCREEN_STATE, screenState);
} else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
- int beamSetting = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
- try {
- IPackageManager mIpm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
- beamSetting = mIpm.getComponentEnabledSetting(new ComponentName(
- BeamShareActivity.class.getPackageName$(),
- BeamShareActivity.class.getName()),
- userId);
- } catch(RemoteException e) {
- Log.e(TAG, "Error int getComponentEnabledSetting for BeamShareActivity");
- }
- synchronized (this) {
- mUserId = userId;
- if (beamSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
- mIsNdefPushEnabled = false;
- } else {
- mIsNdefPushEnabled = true;
+ if (mIsBeamCapable) {
+ int beamSetting =
+ PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ try {
+ IPackageManager mIpm = IPackageManager.Stub.asInterface(
+ ServiceManager.getService("package"));
+ beamSetting = mIpm.getComponentEnabledSetting(new ComponentName(
+ BeamShareActivity.class.getPackageName$(),
+ BeamShareActivity.class.getName()),
+ userId);
+ } catch(RemoteException e) {
+ Log.e(TAG, "Error int getComponentEnabledSetting for BeamShareActivity");
}
+ synchronized (this) {
+ mUserId = userId;
+ if (beamSetting == PackageManager.COMPONENT_ENABLED_STATE_DISABLED) {
+ mIsNdefPushEnabled = false;
+ } else {
+ mIsNdefPushEnabled = true;
+ }
+ }
+ mP2pLinkManager.onUserSwitched(getUserId());
}
- mP2pLinkManager.onUserSwitched(getUserId());
if (mIsHceCapable) {
mCardEmulationManager.onUserSwitched(getUserId());
}
@@ -2588,9 +2591,10 @@
public void onReceive(Context context, Intent intent){
String action = intent.getAction();
if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
- .equals(action)) {
- enforceBeamShareActivityPolicy(context,
- new UserHandle(getSendingUserId()));
+ .equals(action) &&
+ mIsBeamCapable) {
+ enforceBeamShareActivityPolicy(
+ context, new UserHandle(getSendingUserId()));
}
}
};
@@ -2671,7 +2675,8 @@
pw.println("mIsZeroClickRequested=" + mIsNdefPushEnabled);
pw.println("mScreenState=" + ScreenStateHelper.screenStateToString(mScreenState));
pw.println(mCurrentDiscoveryParameters);
- mP2pLinkManager.dump(fd, pw, args);
+ if (mIsBeamCapable)
+ mP2pLinkManager.dump(fd, pw, args);
if (mIsHceCapable) {
mCardEmulationManager.dump(fd, pw, args);
}
diff --git a/src/com/android/nfc/cardemulation/AidRoutingManager.java b/src/com/android/nfc/cardemulation/AidRoutingManager.java
index 8d49649..c7d6edd 100644
--- a/src/com/android/nfc/cardemulation/AidRoutingManager.java
+++ b/src/com/android/nfc/cardemulation/AidRoutingManager.java
@@ -23,6 +23,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -44,7 +45,12 @@
static final int AID_MATCHING_PREFIX_ONLY = 0x02;
// Every routing table entry can be matched either exact or prefix or subset only
static final int AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX = 0x03;
- final int mDefaultRoute;
+
+ int mDefaultIsoDepRoute;
+ //Let mDefaultRoute as default aid route
+ int mDefaultRoute;
+
+ int mMaxAidRoutingTableSize;
final byte[] mOffHostRouteUicc;
final byte[] mOffHostRouteEse;
@@ -71,10 +77,12 @@
private native byte[] doGetOffHostUiccDestination();
private native byte[] doGetOffHostEseDestination();
private native int doGetAidMatchingMode();
+ private native int doGetDefaultIsoDepRouteDestination();
final class AidEntry {
boolean isOnHost;
String offHostSE;
+ int route;
int aidInfo;
}
@@ -93,6 +101,9 @@
Log.d(TAG, "mOffHostRouteEse=" + Arrays.toString(mOffHostRouteEse));
mAidMatchingSupport = doGetAidMatchingMode();
if (DBG) Log.d(TAG, "mAidMatchingSupport=0x" + Integer.toHexString(mAidMatchingSupport));
+
+ mDefaultIsoDepRoute = doGetDefaultIsoDepRouteDestination();
+ if (DBG) Log.d(TAG, "mDefaultIsoDepRoute=0x" + Integer.toHexString(mDefaultIsoDepRoute));
}
public boolean supportsAidPrefixRouting() {
@@ -105,6 +116,23 @@
return mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX;
}
+ public int calculateAidRouteSize(HashMap<String, AidEntry> routeCache) {
+ // TAG + ROUTE + LENGTH_BYTE + POWER
+ int AID_HDR_LENGTH = 0x04;
+ int routeTableSize = 0x00;
+ for(Map.Entry<String, AidEntry> aidEntry : routeCache.entrySet()) {
+ String aid = aidEntry.getKey();
+ // removing prefix length
+ if(aid.endsWith("*")) {
+ routeTableSize += ((aid.length() - 0x01) / 0x02) + AID_HDR_LENGTH;
+ } else {
+ routeTableSize += (aid.length() / 0x02)+ AID_HDR_LENGTH;
+ }
+ }
+ if (DBG) Log.d(TAG, "calculateAidRouteSize: " + routeTableSize);
+ return routeTableSize;
+ }
+
void clearNfcRoutingTableLocked() {
for (Map.Entry<String, Integer> aidEntry : mRouteForAid.entrySet()) {
String aid = aidEntry.getKey();
@@ -139,6 +167,10 @@
NfcService.getInstance().unrouteAids(aid);
}
+ if(NfcService.getInstance().getNciVersion() != NfcService.getInstance().NCI_VERSION_1_0) {
+ // unRoute EmptyAid
+ NfcService.getInstance().unrouteAids("");
+ }
}
private int getRouteForSecureElement(String se) {
@@ -162,6 +194,11 @@
}
public boolean configureRouting(HashMap<String, AidEntry> aidMap) {
+ boolean aidRouteResolved = false;
+ HashMap<String, AidEntry> aidRoutingTableCache = new HashMap<String, AidEntry>(aidMap.size());
+ ArrayList<Integer> seList = new ArrayList<Integer>();
+ seList.add(ROUTE_HOST);
+
SparseArray<Set<String>> aidRoutingTable = new SparseArray<Set<String>>(aidMap.size());
HashMap<String, Integer> routeForAid = new HashMap<String, Integer>(aidMap.size());
HashMap<String, Integer> infoForAid = new HashMap<String, Integer>(aidMap.size());
@@ -180,6 +217,9 @@
}
}
}
+ if (!seList.contains(route))
+ seList.add(route);
+ aidEntry.getValue().route = route;
int aidType = aidEntry.getValue().aidInfo;
String aid = aidEntry.getKey();
Set<String> entries =
@@ -200,91 +240,141 @@
clearNfcRoutingTableLocked();
mRouteForAid = routeForAid;
mAidRoutingTable = aidRoutingTable;
- if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY) {
- /* If a non-default route registers an exact AID which is shorter
- * than this exact AID, this will create a problem with controllers
- * that treat every AID in the routing table as a prefix.
- * For example, if App A registers F0000000041010 as an exact AID,
- * and App B registers F000000004 as an exact AID, and App B is not
- * the default route, the following would be added to the routing table:
- * F000000004 -> non-default destination
- * However, because in this mode, the controller treats every routing table
- * entry as a prefix, it means F0000000041010 would suddenly go to the non-default
- * destination too, whereas it should have gone to the default.
- *
- * The only way to prevent this is to add the longer AIDs of the
- * default route at the top of the table, so they will be matched first.
- */
- Set<String> defaultRouteAids = mAidRoutingTable.get(mDefaultRoute);
- if (defaultRouteAids != null) {
- for (String defaultRouteAid : defaultRouteAids) {
- // Check whether there are any shorted AIDs routed to non-default
- // TODO this is O(N^2) run-time complexity...
- for (Map.Entry<String, Integer> aidEntry : mRouteForAid.entrySet()) {
- String aid = aidEntry.getKey();
- int route = aidEntry.getValue();
- if (defaultRouteAid.startsWith(aid) && route != mDefaultRoute) {
- if (DBG) Log.d(TAG, "Adding AID " + defaultRouteAid + " for default " +
- "route, because a conflicting shorter AID will be " +
- "added to the routing table");
- NfcService.getInstance().routeAids(defaultRouteAid, mDefaultRoute,
- infoForAid.get(defaultRouteAid));
- }
- }
- }
- }
- }
- // Add AID entries for all non-default routes
- for (int i = 0; i < mAidRoutingTable.size(); i++) {
- int route = mAidRoutingTable.keyAt(i);
- if (route != mDefaultRoute) {
- Set<String> aidsForRoute = mAidRoutingTable.get(route);
- for (String aid : aidsForRoute) {
- if (aid.endsWith("*")) {
- if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
- Log.e(TAG, "This device does not support prefix AIDs.");
- } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY) {
- if (DBG) Log.d(TAG, "Routing prefix AID " + aid + " to route "
- + Integer.toString(route));
- // Cut off '*' since controller anyway treats all AIDs as a prefix
- NfcService.getInstance().routeAids(aid.substring(0,
- aid.length() - 1), route, infoForAid.get(aid));
- } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX ||
- mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
- if (DBG) Log.d(TAG, "Routing prefix AID " + aid + " to route "
- + Integer.toString(route));
- NfcService.getInstance().routeAids(aid.substring(0,aid.length() - 1),
- route, infoForAid.get(aid));
- }
- } else if (aid.endsWith("#")) {
- if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
- Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
- + "] is registered");
- } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY ||
- mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX) {
- Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
- + "] is registered");
- } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
- if (DBG) Log.d(TAG, "Routing subset AID " + aid + " to route "
- + Integer.toString(route));
- NfcService.getInstance().routeAids(aid.substring(0,aid.length() - 1),
- route, infoForAid.get(aid));
- }
- } else {
- if (DBG) Log.d(TAG, "Routing exact AID " + aid + " to route "
- + Integer.toString(route));
- NfcService.getInstance().routeAids(aid, route, infoForAid.get(aid));
+ mMaxAidRoutingTableSize = NfcService.getInstance().getAidRoutingTableSize();
+ if (DBG) Log.d(TAG, "mMaxAidRoutingTableSize: " + mMaxAidRoutingTableSize);
+
+ //calculate AidRoutingTableSize for existing route destination
+ for(int index = 0; index < seList.size(); index ++) {
+ mDefaultRoute = seList.get(index);
+ if(index != 0)
+ if (DBG) Log.d(TAG, "AidRoutingTable is full, try to switch mDefaultRoute to 0x" + Integer.toHexString(mDefaultRoute));
+
+ aidRoutingTableCache.clear();
+
+ if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY) {
+ /* If a non-default route registers an exact AID which is shorter
+ * than this exact AID, this will create a problem with controllers
+ * that treat every AID in the routing table as a prefix.
+ * For example, if App A registers F0000000041010 as an exact AID,
+ * and App B registers F000000004 as an exact AID, and App B is not
+ * the default route, the following would be added to the routing table:
+ * F000000004 -> non-default destination
+ * However, because in this mode, the controller treats every routing table
+ * entry as a prefix, it means F0000000041010 would suddenly go to the non-default
+ * destination too, whereas it should have gone to the default.
+ *
+ * The only way to prevent this is to add the longer AIDs of the
+ * default route at the top of the table, so they will be matched first.
+ */
+ Set<String> defaultRouteAids = mAidRoutingTable.get(mDefaultRoute);
+ if (defaultRouteAids != null) {
+ for (String defaultRouteAid : defaultRouteAids) {
+ // Check whether there are any shorted AIDs routed to non-default
+ // TODO this is O(N^2) run-time complexity...
+ for (Map.Entry<String, Integer> aidEntry : mRouteForAid.entrySet()) {
+ String aid = aidEntry.getKey();
+ int route = aidEntry.getValue();
+ if (defaultRouteAid.startsWith(aid) && route != mDefaultRoute) {
+ if (DBG) Log.d(TAG, "Adding AID " + defaultRouteAid + " for default " +
+ "route, because a conflicting shorter AID will be " +
+ "added to the routing table");
+ aidRoutingTableCache.put(defaultRouteAid, aidMap.get(defaultRouteAid));
+ }
+ }
+ }
+ }
+ }
+
+ // Add AID entries for all non-default routes
+ for (int i = 0; i < mAidRoutingTable.size(); i++) {
+ int route = mAidRoutingTable.keyAt(i);
+ if (route != mDefaultRoute) {
+ Set<String> aidsForRoute = mAidRoutingTable.get(route);
+ for (String aid : aidsForRoute) {
+ if (aid.endsWith("*")) {
+ if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
+ Log.e(TAG, "This device does not support prefix AIDs.");
+ } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY) {
+ if (DBG) Log.d(TAG, "Routing prefix AID " + aid + " to route "
+ + Integer.toString(route));
+ // Cut off '*' since controller anyway treats all AIDs as a prefix
+ aidRoutingTableCache.put(aid.substring(0,aid.length() - 1), aidMap.get(aid));
+ } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX ||
+ mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
+ if (DBG) Log.d(TAG, "Routing prefix AID " + aid + " to route "
+ + Integer.toString(route));
+ aidRoutingTableCache.put(aid.substring(0,aid.length() - 1), aidMap.get(aid));
+ }
+ } else if (aid.endsWith("#")) {
+ if (mAidMatchingSupport == AID_MATCHING_EXACT_ONLY) {
+ Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
+ + "] is registered");
+ } else if (mAidMatchingSupport == AID_MATCHING_PREFIX_ONLY ||
+ mAidMatchingSupport == AID_MATCHING_EXACT_OR_PREFIX) {
+ Log.e(TAG, "Device does not support subset AIDs but AID [" + aid
+ + "] is registered");
+ } else if (mAidMatchingSupport == AID_MATCHING_EXACT_OR_SUBSET_OR_PREFIX) {
+ if (DBG) Log.d(TAG, "Routing subset AID " + aid + " to route "
+ + Integer.toString(route));
+ aidRoutingTableCache.put(aid.substring(0,aid.length() - 1), aidMap.get(aid));
+ }
+ } else {
+ if (DBG) Log.d(TAG, "Routing exact AID " + aid + " to route "
+ + Integer.toString(route));
+ aidRoutingTableCache.put(aid, aidMap.get(aid));
+ }
}
- }
+ }
+ }
+
+ if(mDefaultRoute != mDefaultIsoDepRoute) {
+ if(NfcService.getInstance().getNciVersion() != NfcService.getInstance().NCI_VERSION_1_0) {
+ String emptyAid = "";
+ AidEntry entry = new AidEntry();
+ entry.route = mDefaultRoute;
+ if(mDefaultRoute==ROUTE_HOST) {
+ entry.isOnHost = true;
+ } else{
+ entry.isOnHost = false;
+ }
+ entry.aidInfo = RegisteredAidCache.AID_ROUTE_QUAL_PREFIX;
+ aidRoutingTableCache.put(emptyAid, entry);
+ if (DBG) Log.d(TAG, "Add emptyAid into AidRoutingTable");
}
+ }
+
+ if( calculateAidRouteSize(aidRoutingTableCache) <= mMaxAidRoutingTableSize) {
+ aidRouteResolved = true;
+ break;
+ }
+ }
+
+ if(aidRouteResolved == true) {
+ commit(aidRoutingTableCache);
+ } else {
+ Log.e(TAG, "RoutingTable unchanged because it's full, not updating");
+ }
+ }
+ return true;
+ }
+
+ private void commit(HashMap<String, AidEntry> routeCache ) {
+
+ if(routeCache != null) {
+
+ for (Map.Entry<String, AidEntry> aidEntry : routeCache.entrySet()) {
+ int route = aidEntry.getValue().route;
+ int aidType = aidEntry.getValue().aidInfo;
+ String aid = aidEntry.getKey();
+ Log.d (TAG, "commit aid:"+aid+"route:"+route+"aidtype:"+aidType);
+
+ NfcService.getInstance().routeAids(aid, route, aidType);
}
}
// And finally commit the routing
NfcService.getInstance().commitRouting();
-
- return true;
}
/**